Reputation: 7888
I'm sorry, but I generally have a hard time reading the current ctypes docs...
If I have a C function that takes a const char *
pointer, and I know it will neither modify the passed in string, nor keep a reference to it beyond the function call, it really makes sense to pass in a pointer directly to the bytes of a python string.
Can ctypes can do this or is it just plain unsupported? Do I really have to create_string_buffer
and copy my string into it?
Upvotes: 7
Views: 22116
Reputation: 351
Assigning a new value to instances of the pointer types c_char_p, c_wchar_p, and c_void_p changes the memory location they point to, not the contents of the memory block (of course not, because Python strings are immutable):
>>> s = "Hello, World" >>> c_s = c_char_p(s) >>> print c_s c_char_p('Hello, World') >>> c_s.value = "Hi, there" >>> print c_s c_char_p('Hi, there') >>> print s # first string is unchanged Hello, World >>>
You should be careful, however, not to pass them to functions expecting pointers to mutable memory. If you need mutable memory blocks, ctypes has a create_string_buffer function which creates these in various ways. The current memory block contents can be accessed (or changed) with the raw property, if you want to access it as NUL terminated string, use the string property:
Says the ctypes tutorial. What I gather from this is that only if the function would work with a const char*
, would passing in the python string be valid. Keep in mind, it won't have a null termination.
I'd suggest using create_string_buffer
anyhow.
Upvotes: 18
Reputation: 177971
The type ctypes.c_char_p represents a nul-terminated string. If a function takes a const char* you can pass a Python string to it and it will receive a nul-terminated version.
A Windows example DLL:
#include <string.h>
__declspec(dllexport) char* func(char* a,size_t len,const char* b)
{
if(strlen(b) * 2 >= len)
return NULL;
strcpy_s(a,len,b);
strcat_s(a,len,b);
return a;
}
Python:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> x=CDLL('x')
>>> x.func.restype=c_char_p
>>> x.func.argtypes=[c_char_p,c_int,c_char_p]
>>> s=create_string_buffer(10)
>>> x.func(s,len(s),'abcd')
'abcdabcd'
>>>
Upvotes: 6