Thanks to @ErykSun the solution:
Python code
string1 = "my string 1"
string2 = "my string 2"
# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')
# send strings to c function
my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
my_c_function(b_string1, b_string2)
Answer from MorphieBlossom on Stack OverflowThanks to @ErykSun the solution:
Python code
string1 = "my string 1"
string2 = "my string 2"
# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')
# send strings to c function
my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
my_c_function(b_string1, b_string2)
I think you just need to use c_char_p() instead of create_string_buffer().
string1 = "my string 1"
string2 = "my string 2"
# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')
# send strings to c function
my_c_function(ctypes.c_char_p(b_string1),
ctypes.c_char_p(b_string2))
If you need mutable strings then use create_string_buffer() and cast those to c_char_p using ctypes.cast().
ctypes.cast() is used to convert one ctype instance to another ctype datatype. You don't need it To convert it to python string. Just use ".value" to get it in python string.
>>> s = "Hello, World"
>>> c_s = c_char_p(s)
>>> print c_s
c_char_p('Hello, World')
>>> print c_s.value
Hello, World
More info here
If you set the argtypes or restype attributes of ctypes functions, they will return the right Python object without the need for a cast.
Here's an example calling the C-runtime time and ctime functions:
>>> from ctypes import *
>>> m=CDLL('msvcrt')
>>> t=c_long(0)
>>> m.time(byref(t))
1326700130
>>> m.ctime(byref(t)) # restype not set
6952984
>>> m.ctime.restype=c_char_p # set restype correctly
>>> m.ctime(byref(t))
'Sun Jan 15 23:48:50 2012\n'
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.
Maybe by using restype like described here
class Test(object):
def __init__(self):
self.test_library=CDLL("./test.so")
self.test_initialize = self.test_library.initializetest
self.test_initialize.argtypes = []
self.test_initialize.restype = c_char_p # c_char_p is a pointer to a string
self.test_search = self.test_library.searchtest
self.test_search.restype = c_int
self.test_search.argtypes = [c_char_p]
self.m = c_char_p(self.test_initialize())
def search(self):
return self.test_search(self.m).value
r = Test()
print r.search()
EDIT: corrected after test :)
For anyone who finds this, in Python 3 string and bytes are now different. ctypes needs a bytes instance in order to correctly pass the parameter as char*.
test_lib.get_val(b'Test1', byref(a)) will pass the full 'Test1' as a char* to the c function
test_lib.get_val('Test1', byref(a)) will not pass 'Test1' as a char*, from my little bit of testing it passes the first letter of the python str followed by a null charcter.
1: What is Happening
ctypes does adapt the Python string, correctly guessing that the function takes a char*. Effectively, libx.foo("string") is equivalent to the second example libx.foo(c_char_p("string")) with a little runtime adaptation.
Your intuition about the string being garbage collected shortly after the call is correct. Nothing in Python retains a reference to the adapted c_char_p view of the string, and thus it will be returned to the object pool — likely to be re-issued in the future. Which means that the char* c_ptr will probably point at junk very soon.
2: Different in Effect
The second form allows you to keep a reference to the view passed to the C function. If you changed the example slightly:
>>> s = c_char_p("string")
>>> libx.foo(s)
Then as long as a reference is maintained to s, the c_ptr value will be valid. You could accomplish that by just keeping a reference in the module implementing your binding to libx.