简体   繁体   English

使用ctypes将字符串从Python传递到C共享库的问题

[英]Issue with passing string from Python to C shared lib using ctypes

I'm having difficulty passing string from Python to C by ctypes: 我很难通过ctypes将字符串从Python传递给C:

My C code(compiled into a hello.so) 我的C代码(编译成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: 我的Python代码:

...
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 the error: hello_args = TEST_STRUCT(1, name) TypeError: expected string, c_char_Array_5 found 我收到错误:hello_args = TEST_STRUCT(1,name)TypeError:expected string,c_char_Array_5 found

I tried to change c_char_p to c_wchar_p or c_char*5 or c_wchar*5 etc. Sometimes it can run without error, the first int parameter of the struct can be printed correctly, but not the second string pointer, the best I can get is just the first character 't' instead of the whole word "test". 我试图将c_char_p更改为c_wchar_p或c_char * 5或c_wchar * 5等。有时它可以正常运行,结构的第一个int参数可以正确打印,但不是第二个字符串指针,我能得到的最好只是第一个字符't'而不是整个单词“test”。

BTW, my python3 version is 3.3.0 顺便说一句,我的python3版本是3.3.0

The solution depends on whether you need the data type to be mutable (from Python's perspective). 解决方案取决于您是否需要数据类型是可变的(从Python的角度来看)。

If don't need the data to be mutable, then don't bother with the buffer constructor. 如果不需要数据是可变的,那么不要打扰缓冲区构造函数。 Just pass the bytes object direct to the TEST_STRUCT constructor. 只需将bytes对象直接传递给TEST_STRUCT构造函数即可。 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 then you need to specify your char* type slightly differently in the TEST_STRUCT class. 如果需要可变缓冲区,则需要在TEST_STRUCT类中稍微不同地指定char*类型。 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 versus POINTER(c_char) c_char_pPOINTER(c_char)

Ostensibly, whilst these two appear similar they are subtly different. 表面上看,虽然这两个看起来很相似但却略有不同。 POINTER(c_char) is for any buffer of char data. POINTER(c_char)用于char数据的任何缓冲区。 c_char_p is specifically for NULL terminated strings. c_char_p专门用于NULL终止字符串。 As a side effect of this condition all c_char_p objects are immutable (on the python side) so as to make this guarantee easier to enforce. 作为这种情况的副作用,所有c_char_p对象都是不可变的(在python端),以便使这种保证更容易实施。 eg. 例如。 {65, 66, 67, 0} is a string ( "ABC" ), whereas {1, 2, 3} would not be. {65, 66, 67, 0}是一个字符串( "ABC" ),而{1, 2, 3}不是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM