I have a simple C-file:
char* initializetest() {
char * test = malloc(1000);
return test;
}
int searchtest( char* test )
{
strcpy(test,"test");
return 0;
}
main()
{
char *test = initializetest();
searchtest(test);
printf("%s\n", test );
}
and python file:
from ctypes import *
class Test(object):
def __init__(self):
self.test_library=CDLL("test.so")
self.test_initialize = self.test_library.initializetest
self.test_search = self.test_library.searchtest
self.test_search.restype=c_int
self.m = self.test_initialize()
def search(self):
self.test_search(self.m)
print self.m
r = Test()
print r.search()
How to get "test" string in python ?
from ctypes import *
charptr = POINTER(c_char)
test = CDLL('test.so')
test.initializetest.argtypes = []
test.initializetest.restype = charptr
test.searchtest.argtypes = [charptr]
test.searchtest.restype = c_int
buf = test.initializetest()
test.searchtest(buf)
print cast(buf, c_char_p).value
# TODO Release the "buf" memory or it will leak.
EDIT
Initially I used c_char_p
to pass the buffer between the functions but c_char_p
is like a const pointer. If used as a restype
, you will actually get a Python str
back. So for initializetest
it will create a string from the allocated memory (by copying data) and throw the pointer away.
Now we're creating a new type, a POINTER
to c_char
. This is then used in both functions.
For Python, this type points to a single char so we have to cast it to get the whole string after searchtest
is done. We cast to c_char_p
because we just want to read the value so a const pointer is OK.
As a side note, this illustrates the disastrous effect of using c_char_p
with functions that modify the array (as searchtest
above does):
>>> libc.memset.argtypes = [c_char_p, c_int, c_int]
>>> foo = 'Python'
>>> foo
'Python'
>>> libc.memset(foo, ord('x'), 3)
44808532
>>> foo
'xxxhon'
>>>
Note how we've managed to change an immutable Python string!
The argtypes
setup line isn't even needed because ctypes
assumes c_char_p
if Python str
is used as argument.