2015-05-21 11 views
5

Hier ist mein C-Code, ich habe eine gemeinsame Lib daraus gemacht. Wenn ich die freigegebene Lib in Python lade und den unten stehenden Python-Code ausführe, stürzt ich ab. Warum?Warum stürzt Python beim Zurückgeben einer C-Zeichenfolge ab?

extern "C" { 
PyObject* foo2(char* b) 
{ 
    return Py_BuildValue("s", b); 
} 

} 

Und hier ist, was ich in Python tue:

from ctypes import * 
    d = cdll.LoadLibrary('./foo.so') 
    d.foo2.restype = c_char_p 
    v = d.foo2('hello world') 
    print pythonapi.PyString_Size(v) 

Wenn es hilft, ich bin python2.6.

+1

'c_char_p' - bedeutet das nicht' char * '? Sie sind ** nicht ** zurückgeben ein 'char *' ... –

+1

Warum verwenden Sie 'ctypes', um eine Bibliothek zu öffnen, die die Python-API verwendet, anstatt diese Bibliothek zu einem Python-Erweiterungsmodul zu machen? – interjay

Antwort

4

Sie sagen cdll, dass die Funktion eine char* zurückgibt, aber tatsächlich eine PyObject* zurückgibt. Die beiden müssen übereinstimmen.

9

Ihr Problem ist, dass Sie über den Rückgabetyp lügen:

d.foo2.restype = c_char_p 

Der tatsächliche Rückgabetyp ist PyObject *. Aber ctypes wird sehen, dass c_char_p, werfen Sie die PyObject * auf eine char *, und versuchen Sie dann, dass char * in eine Zeichenfolge mit PyString_FromString konvertieren, die wer weiß, was Bytes, bis es ein NUL-Zeichen trifft liest.

Die Art, eine PyObject * anzugeben, ist mit py_object.

Auch möchten Sie wahrscheinlich die argtype s setzen. Und dieses Mal ist es wirklich ist ein c_char_p:

d = cdll.LoadLibrary('./foo.so') 
d.foo2.argtypes = [c_char_p] 
d.foo2.restype = py_object 

Aber wie interjay in einem Kommentar weist darauf hin, es ist ein bisschen albern ist eine C-Bibliothek zu bauen, der die Python C-API verwendet, und ruft dann über ctypes. Dies ist gelegentlich nützlich, aber normalerweise ist die Lösung, nur ein C-Erweiterungsmodul zu bauen, anstatt 80% der Arbeit für keinen der Vorteile zu tun ...

Verwandte Themen