从库返回的ctypes结构 [英] ctypes struct returned from library

查看:43
本文介绍了从库返回的ctypes结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出一个简单的C文件:

Given a simple C file:

#include <stdio.h>

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

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

我有一个简单的python文件:

And I have a simple python file:

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())

如何将返回的值设置为具有 {1、2} 值的结构 POINT ?

How can I set my returned value to the struct POINT with values {1, 2}?

推荐答案

您所要问的只是示例中唯一的问题.只是回答您首先要问的问题:您必须注释C函数返回类型,以便ctypes知道它是一个内存地址-否则默认情况下它是一个(4字节)整数(在任何64位OS中,指针是8个字节长).

What you ar asking is nto the sole problem in your example. Just to answer just what you asked first: you have to annotate the C function return type, so that ctypes know it is a memory address - otherwise it is a (4 byte) integer by default (while in any 64 bit OS, pointers are 8 bytes long).

然后,您可以使用(隐藏)创建Python侧POINT结构您的POINT类中的"from_address"方法:

Then you can create Python side POINT structures by using the (hidden) "from_address" method in your POINT class:

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 运行时存在,并随后被释放.上面的代码将导致分段错误.

Before that works, however, you have a more fundamental issue on the C side: the POINT structure you declare on your example only exists while get_point is running, and is deallocated afterwards. The code above would lead to a segmentation fault.

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

Your C code have to allocate memory properly. And also, you should take provisions to deallocate data structures you allocate in C - otherwise you will have memory leaks as each call to the function in C allocates more memory and you don't free that. (Notice that this memory won't be freed by itself when the Python POINT object goes out of scope).

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

Your C code could be like this:

#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部分中:

And with this Python part:

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示例,我将添加GCC命令来构建testlib文件:

(just so that this answer is a complete ctypes example, I will add the GCC commands to build the testlib file:

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

)

这篇关于从库返回的ctypes结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆