从库返回的ctypes结构

时间:2016-07-29 14:44:38

标签: python c python-2.7 wrapper ctypes

给出一个简单的C文件:

document.form1.input1.style.backgroundColor = '#fff';

我有一个简单的python文件:

#include <stdio.h>

typedef struct point {
    int x;
    int y;
} POINT; 

POINT get_point() 
{
    POINT p = {1, 2};
    return p;
}

如何将返回值设置为值为from ctypes import * import os lib_name = '/testlib.so' test_lib = CDLL(os.getcwd() + lib_name) class POINT(Structure): _fields_ = [('x', c_int), ('y', c_int)] # Sets p1 to the integer 1 p1 = test_lib.get_point() # Sets p2 to the struct POINT with values {1, 0} p2 = POINT(test_lib.get_point()) 的结构POINT

1 个答案:

答案 0 :(得分:1)

你要问的是你的例子中唯一的问题。 只是为了回答你刚才问的问题:你必须注释C函数返回类型,这样ctypes就知道它是一个内存地址 - 否则它默认是一个(4字节)整数(而在任何64字节操作系统中,指针都是8个字节长。)

然后你可以使用(隐藏)创建Python端POINT结构 POINT类中的“from_address”方法:

test_lib.get_point.restype = c_void_p
p = POINT.from_address(test_lib.get_point())

print(p.x, p.y)

然而,在此之前,你在C方面有一个更基本的问题: 您在示例中声明的POINT结构仅在get_point运行时存在,并在之后被释放。上面的代码会导致分段错误。

您的C代码必须正确分配内存。而且,您应该采取措施来释放您在C中分配的数据结构 - 否则您将有内存泄漏,因为在C中对函数的每次调用都会分配更多内存而您不会释放它。 (请注意,当Python POINT对象超出范围时,此内存不会自行释放。)

你的C代码可能是这样的:

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

typedef struct point {
    int x;
    int y;
} POINT;

POINT *get_point()
{
    POINT *p;
    POINT initial = {1, 2};
    p = malloc(sizeof(POINT));
    *p = initial;
    return p;
}

void free_point(POINT *p)
{
    free(p);
}

使用这个Python部分:

from ctypes import *
import os

lib_name = '/testlib.so'
test_lib = CDLL(os.getcwd() + lib_name)

class POINT(Structure):
    _fields_ = [('x', c_int),
                ('y', c_int)]

test_lib.get_point.restype = c_void_p

p1 = POINT.from_address( test_lib.get_point())
print (p1.x, p1.y)

test_lib.free_point(byref(p1))
del p1

一切都应该有效。

(只是这个答案是一个完整的ctypes示例,我将添加 用于构建testlib文件的GCC命令:

gcc -c -fPIC test.c -o test.o
gcc test.o -shared -o testlib.so