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 argtypes. 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