Hallo Leute,
ich suche vergeblich ein Beispiel wie ich von einer C Extension Function ein Python builtin array zurueckgeben kann.
Ich möchte nicht NumPy installieren müssen, sondern das vorhandene benutzen, eine Zugriffsmöglichkeit von C ist aber nirgends so richtig dokumentiert.
Wer hat da einen Tip?
builtin array von c ext function zurückgeben
... und wie man das mit dem array-Modul macht weiß ich auch nicht, aber Du hast gute Chancen die Fragen unter comp.lang.python beantwortet zu bekommen.
HTH,
Christian
HTH,
Christian
Du meinst entweder ein Tupel oder eine Liste.
Siehe
http://docs.python.org/api/tupleObjects.html
und
http://docs.python.org/api/listObjects.html
Siehe
http://docs.python.org/api/tupleObjects.html
und
http://docs.python.org/api/listObjects.html
Soweit ich verstanden habe, Joghurt, meint er das array-Modul. Das API wird ähnlich sein, wie bei List Objects, aber die Frage scheint: Wie kann man erreichen, daß ein 'array' zurückgegeben wird? Hast Du da einen Link - ich habe nichts finden können.
Oder gibt es hier ein Mißverständnis? iwl, Deine Gelegenheit zur Klarstellung .
Gruß,
Christian[/list]
Oder gibt es hier ein Mißverständnis? iwl, Deine Gelegenheit zur Klarstellung .
Gruß,
Christian[/list]
Wahrscheinlich ist es am einfachsten, in C mit einem normalen C-Array zu arbeiten, das dann mit PyString_FromStringAndSize in einen Python-String umzuwandeln und an das Python-Script zurückzuliefern. Hier dürfte dann die Umwandlung in ein array, wenn sie denn überhaupt noch nötig sein sollte, kein Problem mehr sein.
Hier ein Beispiel:Wenn man nicht den Ausgangsstring verändern will, muss man Speicher für den neuen String holen und wieder freigeben. Der Einfachheit halber habe ich für die Demo darauf verzichtet.
Und ein Beispiel mit Floats:
Das meiste dabei sind Anweisungen zur Ausgabe, die das Ergebnis verdeutlichen sollen. Der reine Datenaustausch kostet gerade mal 5 Zeilen.
MfG
HWK
Hier ein Beispiel:
Code: Alles auswählen
/* File CArray.c */
/* Python-String in C als C-Array bearbeiten. */
#include <Python.h>
static PyObject *carray(PyObject *self, PyObject *args)
{
char *str;
int slen, i;
if (!PyArg_ParseTuple(args, "s#", &str, &slen))
return NULL;
for(i = 0; i < slen; i++)
str[i] += 1; // Verändert direkt den Ausgangsstring
return PyString_FromStringAndSize(str, slen);
}
static PyMethodDef CArrayMethods[] = {
{"carray", carray, METH_VARARGS,
"Python-String in C als C-Array bearbeiten."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initcarray()
{
Py_InitModule("carray", CArrayMethods);
}
Code: Alles auswählen
# File setup.py
from distutils.core import setup, Extension
carray = Extension('carray', sources=['CArray.c'])
setup(name='carray', version='0.1',
description='Python-String in C als C-Array bearbeiten.',
ext_modules=[carray])
Code: Alles auswählen
# File CArray.py
from array import array
from binascii import hexlify
from carray import carray
text = '\x00\x5aHallo\xFF'
print hexlify(text)
print hexlify(carray(text))
array_ = array('c', text)
array_.reverse()
print array_
Code: Alles auswählen
from array import array
from binascii import hexlify
from struct import pack, unpack
from carray import carray
double = [1.0, 2.0, 3.0]
text = ''
for num in double:
text += pack('d', num)
print double
print hexlify(text)
print hexlify(carray(text))
for i in range(0, len(text) / 8):
double[i] = unpack('d', text[8 * i:8 * (i + 1)])
print double
array_ = array('d', text)
array_.reverse()
print array_
MfG
HWK
Hoi,
Deinen Lösungsvorschlag, HWK, finde ich erst einmal nicht schlecht. Aber mir ist noch eingefallen (hätte ich auch eher drauf kommen können ), das es da ja noch den Quellcode des Arraymoduls gibt. Vielleicht hilft ein Blick dort hinein auch weiter.
Gruß,
Christian
Deinen Lösungsvorschlag, HWK, finde ich erst einmal nicht schlecht. Aber mir ist noch eingefallen (hätte ich auch eher drauf kommen können ), das es da ja noch den Quellcode des Arraymoduls gibt. Vielleicht hilft ein Blick dort hinein auch weiter.
Gruß,
Christian
HWK hat geschrieben:@iwl: Hast Du Dein Problem jetzt gelöst? Wenn ja, wie denn?
MfG
HWK
Code: Alles auswählen
[...]
#define Ret0 return NULL
[...]
PyObject * ps_ArrayFunc=0, * ps_fTuple=0;
#define DR Py_DECREF
static PyObject * ps_makePyFloatArray(float * buf, int values)
{ PyObject * PyBuf, * Func, * Tuple, * Array, * Ret;
if(!ps_ArrayFunc)
{ PyObject * Module = PyImport_ImportModule("array");
if(!Module) Ret0;
ps_ArrayFunc=PyObject_GetAttrString(Module, "array");
DR(Module);
if(!ps_ArrayFunc) Ret0;
}
if(!ps_fTuple) if((ps_fTuple=Py_BuildValue("(s)", "f"))==0) Ret0;
if((Array=PyObject_CallObject(ps_ArrayFunc, ps_fTuple))==0) Ret0;
if((Func=PyObject_GetAttrString(Array, "fromstring"))==0) { DR(Array); Ret0; }
if((Tuple=PyTuple_New(1))==0) { DR(Array); DR(Func); Ret0; }
if((PyBuf=PyBuffer_FromMemory(buf, values*sizeof(float)))==0)
{ DR(Array); DR(Func); DR(Tuple); Ret0; }
PyTuple_SetItem(Tuple, 0, PyBuf);
Ret=PyObject_CallObject(Func, Tuple);
DR(Func); DR(Tuple);
if(!Ret) Ret0;
DR(Ret);
return(Array);
}
//---------------------------------------------------------------------------
[...]
void initps(void)
{ ps_ArrayFunc=ps_fTuple=0;
[...]
Eigentlich sollte die array-funktion auch einen Buffer akzeptieren, das wäre wohl im Sinne des arrays, aber geht halt nicht.
Toll gemacht!
Ich glaub, ich hab's weitgehend verstanden. Die Referenzen erfordern ja doch ziemlich viel Aufmerksamkeit. Was mir noch unklar ist: Müsste man nicht array.fromstring() einen String und kein Tuple übergeben?
MfG
HWK
[Edit]: Funktioniert Deine Idee nicht doch, z.B. so (ungetestet)?Py_BuildValue macht ja aus dem Buffer einen Python-String, den ich an array übergeben kann. Müsste ich dann eigentlich ps_fTuple am Schluss dereferenzieren?
MfG
HWK
Ich glaub, ich hab's weitgehend verstanden. Die Referenzen erfordern ja doch ziemlich viel Aufmerksamkeit. Was mir noch unklar ist: Müsste man nicht array.fromstring() einen String und kein Tuple übergeben?
MfG
HWK
[Edit]: Funktioniert Deine Idee nicht doch, z.B. so (ungetestet)?
Code: Alles auswählen
[...]
#define Ret0 return NULL
[...]
PyObject * ps_ArrayFunc=0;
#define DR Py_DECREF
static PyObject * ps_makePyFloatArray(float * buf, int values)
{ PyObject * ps_fTuple, * Array;
if(!ps_ArrayFunc)
{ PyObject * Module = PyImport_ImportModule("array");
if(!Module) Ret0;
ps_ArrayFunc=PyObject_GetAttrString(Module, "array");
DR(Module);
if(!ps_ArrayFunc) Ret0;
}
if((ps_fTuple=Py_BuildValue("(ss#)", "f", buf, values*sizeof(float)))==0) Ret0;
if((Array=PyObject_CallObject(ps_ArrayFunc, ps_fTuple))==0) Ret0;
return(Array);
}
//---------------------------------------------------------------------------
[...]
void initps(void)
{ ps_ArrayFunc=0;
[...]
MfG
HWK
Es klappt wirklich. Ich habe zum Testen mal mein erstes Beispiel entsprechend verändert:Somit ist es kaum länger als die Umwandlung in einen String, wenn man einmal vom notwendigen Importieren des array-Moduls absieht.
MfG
HWK
Code: Alles auswählen
/* File CArray.c */
/* C-Array aus Floats in Python array.array umwandeln. */
#include <Python.h>
static PyObject *ps_ArrayFunc = NULL;
static PyObject *carray(PyObject *self, PyObject *args)
{
char *str;
int slen;
PyObject *ps_fTuple, *Array;
if (!PyArg_ParseTuple(args, "s#", &str, &slen))
return NULL;
if (!ps_ArrayFunc) {
PyObject *Module = PyImport_ImportModule("array");
if (!Module)
return NULL;
ps_ArrayFunc = PyObject_GetAttrString(Module, "array");
Py_DECREF(Module);
if (!ps_ArrayFunc)
return NULL;
}
if (!(ps_fTuple = Py_BuildValue("(ss#)", "d", str, slen)))
return NULL;
Array = PyObject_CallObject(ps_ArrayFunc, ps_fTuple);
Py_DECREF(ps_fTuple);
return(Array);
}
static PyMethodDef CArrayMethods[] = {
{"carray", carray, METH_VARARGS,
"C-Array aus Floats in Python array.array umwandeln."},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initcarray()
{
Py_InitModule("carray", CArrayMethods);
}
Code: Alles auswählen
# File CArray.py
from struct import pack
from carray import carray
double = [1.0, 2.0, 3.0]
text = ''
for num in double:
text += pack('d', num)
print double
print carray(text)
MfG
HWK