Problem with passing a string from Python to C shared lib using ctypes

It's hard for me to pass a string from Python to C by ctypes:

My C code (compiled in hello.so)

... typedef struct test{ unsigned int a; unsigned char* b; } my_struct; int hello(my_struct *in) { FILE *fp; ... fprintf(fp, "%d\t%s\n", in->a, in->b); fclose(fp); return 0; } 

My Python code is:

 ... from ctypes import * ... class TEST_STRUCT(Structure): _fields_ = [("a", c_int), ("b", c_char_p)] ... hello_lib = ctypes.cdll.LoadLibrary("hello.so") hello = hello_lib.hello hello.argtypes = [POINTER(TEST_STRUCT)] name = create_string_buffer(b"test") hello_args = TEST_STRUCT(1, name) hello(ctypes.byref(hello_args)) ... 

I get an error: hello_args = TEST_STRUCT (1, name) TypeError: expected string, c_char_Array_5 found

I tried changing c_char_p to c_wchar_p or c_char * 5 or c_wchar * 5 etc. Sometimes it can run without errors, the first parameter of the int structure can be printed correctly, but not the second line pointer, get is only the first character 't' instead of the whole word "test".

BTW, my python3 version is 3.3.0

+5
source share
1 answer

The decision depends on whether you need the data type to be changed (from a Python perspective).

If you do not need the data to be modified, then do not worry about the buffer constructor. Just pass the bytes object directly to the TEST_STRUCT constructor. eg.

 from ctypes import * class TEST_STRUCT(Structure): _fields_ = [("a", c_int), ("b", c_char_p)] hello_args = TEST_STRUCT(1, b"test") 

If you need a mutable buffer, you need to specify your char* type somewhat differently in the TEST_STRUCT class. eg.

 from ctypes import * class TEST_STRUCT(Structure): _fields_ = [("a", c_int), ("b", POINTER(c_char))] # rather than c_char_p name = create_string_buffer(b"test") hello_args = TEST_STRUCT(1, name) 

c_char_p compared to POINTER(c_char)

Allegedly, although these two seem similar, they are slightly different from each other. POINTER(c_char) - for any char data buffer. c_char_p is for null-terminated strings. As a side effect of this condition, all c_char_p objects c_char_p immutable (from the python side) to simplify this guarantee. eg. {65, 66, 67, 0} is the string ( "ABC" ), while {1, 2, 3} will not.

+1
source

All Articles