Here's my C code, I made a shared lib out of it. When I load the shared lib in Python and execute the Python code below, I crash. Why?
extern "C" {
PyObject* foo2(char* b)
{
return Py_BuildValue("s", b);
}
}
And here's what I am doing in Python:
from ctypes import *
d = cdll.LoadLibrary('./foo.so')
d.foo2.restype = c_char_p
v = d.foo2('hello world')
print pythonapi.PyString_Size(v)
If it helps, I am at Python2.6.
Your problem is that you're lying about the return type:
d.foo2.restype = c_char_p
The actual return type is PyObject *
. But ctypes
is going to see that c_char_p
, cast the PyObject *
to a char *
, and then try to convert that char *
to a string with PyString_FromString
, which is going to read who knows what arbitrary bytes until it hits a NUL character.
The way to specify a PyObject *
is with py_object
.
Also, you probably want to set the argtype
s. And this time, it really is a c_char_p
:
d = cdll.LoadLibrary('./foo.so')
d.foo2.argtypes = [c_char_p]
d.foo2.restype = py_object
But, as interjay points out in a comment, it's a bit silly to be building a C library that uses the Python C API and then calling it via ctypes
. This is occasionally useful, but normally, the solution is to just finish building a C extension module instead of doing 80% of the work for none of the benefit…
You are telling cdll
that the function returns a char*
but in actual fact it returns a PyObject*
. The two need to be in agreement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With