Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python ctypes-查看返回结构的c_char_p字段_Python_C_Struct_Binding_Ctypes - Fatal编程技术网

Python ctypes-查看返回结构的c_char_p字段

Python ctypes-查看返回结构的c_char_p字段,python,c,struct,binding,ctypes,Python,C,Struct,Binding,Ctypes,我定义了一个名为TestStruct的简单C结构和一个函数init\u struct来创建一个实例并返回指向它的指针 #include <stdlib.h> #include <stdio.h> typedef struct { int x; int y; char* msg; } TestStruct; TestStruct* init_struct(int x, int y, char* msg) { TestStruct* p;

我定义了一个名为
TestStruct
的简单C结构和一个函数
init\u struct
来创建一个实例并返回指向它的指针

#include <stdlib.h>
#include <stdio.h>

typedef struct {
    int x;
    int y;
    char* msg;
} TestStruct;

TestStruct* init_struct(int x, int y, char* msg) {
    TestStruct* p;
    TestStruct initial = {x, y, msg};
    p = malloc(sizeof(TestStruct));
    *p = initial;
    return p;
}

结构的整数成员(
x
y
)打印得很好,但我不知道如何打印
msg
指向的字符串。我看到的不是预期的
helloworld
,而是一个字节字符串
b'\x01
。我从其他阅读中得到的直觉是,我正在截断真正的较长字符串,只显示第一个字节。

您正在将
ctypes.c_char_p(b'hello world')
传递到
init_struct
并将赋值中指向
c_char_p
块的指针复制到
initial
p
。但是,指向
c\u char\u p
块的指针仅在调用
init\u struct
期间有效,也就是说,一旦
init\u struct
返回,
c\u char\u p
指针将不再有效,访问它将是未定义的行为。换句话说,您在
myStruct.msg
中获取的指针副本是悬空的,不应在
init\u struct
之外访问

请记住,
ctypes
并不违反Python的垃圾收集(GC)规则。在这一行中,
myStruct=\u init\u struct(1,4,ctypes.c\u char\u p(b'hello world'))
ctypes
将分配一些
c\u char\u p
对象,在字符串b
hello world
中复制,空终止它,并将指向该内存的原始指针传递到c端。然后C端运行,代码获取该指针的副本。当C端返回时,
ctypes
释放对
C\u char\p
对象的引用。Python的GC然后发现
c\u char\p
不再被引用,因此它被垃圾收集。因此,您最终会在
myStruct.msg
中看到一个悬空指针

正确的解决方案是克隆
msg
中的
init_-struct
内容,并提供
fini_-struct
函数,以便在完成克隆后释放该克隆内存,例如:

#include <stdlib.h>
#include <stdio.h>

typedef struct {
    int x;
    int y;
    char* msg;
} TestStruct;

TestStruct* init_struct(int x, int y, char* msg) {
    TestStruct* p = malloc(sizeof(TestStruct));
    p->x = x;
    p->y = y;
    p->msg = strdup(msg);
    return p;
}

void fini_struct(TestStruct* p) {
    free(p->msg);
    free(p);
}

也许您需要将bytestream转换为string?仅供参考,您可以直接传递
b'hello world'
,而无需使用
ctypes.c_char_p(b'hello world')
wrapping.about:
p=malloc(sizeof(TestStruct))*p=初始值1)应始终检查(!=NULL)返回值,以确保发送到
mallloc
的操作成功。2) 第二条语句不会复制
initial的内容。建议使用:
strncpy(p,&initial,sizeof(TestStruct))`
#include <stdlib.h>
#include <stdio.h>

typedef struct {
    int x;
    int y;
    char* msg;
} TestStruct;

TestStruct* init_struct(int x, int y, char* msg) {
    TestStruct* p = malloc(sizeof(TestStruct));
    p->x = x;
    p->y = y;
    p->msg = strdup(msg);
    return p;
}

void fini_struct(TestStruct* p) {
    free(p->msg);
    free(p);
}
import ctypes
import os

class PyStruct(ctypes.Structure):
    _fields_ = [('x', ctypes.c_int), 
                ('y', ctypes.c_int),         
                ('msg', ctypes.c_char_p)]

lib = ctypes.cdll.LoadLibrary(os.path.abspath('/path/to/libstruct.so'))
_init_struct = lib.init_struct
_init_struct.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_char_p]
_init_struct.restype = ctypes.POINTER(PyStruct)

_fini_struct = lib.fini_struct
_fini_struct.argtypes = [ctypes.POINTER(PyStruct)]

myStruct = _init_struct(1, 4, ctypes.c_char_p(b'hello world'))
print(myStruct.contents.x, myStruct.contents.y, myStruct.contents.msg)

# when you are done with myStruct
_fini_struct(myStruct)