使用ctypes将Struct从C返回到Python的问题

6rqinv9w  于 2023-02-11  发布在  Python
关注(0)|答案(2)|浏览(149)

我试图使用ctype从python中获取C结构成员变量的值。我期望x和y的返回值分别是10和20。我想我可能忽略了一些微妙的东西,但不确定是什么。我得到的输出是x和y的0,如文章末尾所示。感谢任何指针。

    • Python代码:**
import ctypes
import os

class Point(ctypes.Structure):
    _fields_ = [("x", ctypes.c_int), 
                ("y", ctypes.c_int)]

directory = os.path.dirname(os.path.realpath(__file__))
print(directory)
source = directory + "\\cstruct.so"
 
clibrary = ctypes.CDLL(source)

clibrary.getPoint.restype = ctypes.POINTER(Point)
p1 = clibrary.getPoint()
print(p1.contents.x, p1.contents.y)
    • C代码:**
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct Point
{
    int x;
    int y;
};

struct Point* getPoint()
{
    struct Point *p;
    p->x = 10;
    p->y = 20;
    return p;
}

C代码被编译成一个共享库文件www.example.com,在python文件中调用。cstruct.so which is called in the python file.

    • Python输出:**
0 0
rnmwe5a2

rnmwe5a21#

我发现了问题所在,我必须动态分配C文件中struct Point的大小,以前我没有这样做过,这样就解决了问题。
只是修改了struct Point* getPoint()函数中的第一行,如下所示。

struct Point *p = malloc(sizeof(struct Point));

还在c文件中添加了一个C函数,以释放结构指针的内存,如下所示。

void free_mem(struct Point* p) 
{
    free(p);
}
neekobn8

neekobn82#

原始代码没有为该结构分配内存,所以我认为“问题”是崩溃。
一种解决方案是修改代码,让Python分配和管理内存,以消除返回但未释放堆分配对象时发生内存泄漏的可能性。
test.c

#define API __declspec(dllexport)  // For Windows

struct Point {
    int x;
    int y;
};

API void getPoint(struct Point* p) {
    p->x = 10;
    p->y = 20;
}

test.py

import ctypes as ct
import os

class Point(ct.Structure):
    _fields_ = [("x", ct.c_int), 
                ("y", ct.c_int)]
    # define display representation of a Point so it can print itself.
    def __repr__(self):
        return f'Point(x={self.x}, y={self.y})'

dll = ct.CDLL('./test')
dll.getPoint.argtypes = ct.POINTER(Point),
dll.getPoint.restype = None

p = Point()                # Python creates an instance and manages the lifetime.
dll.getPoint(ct.byref(p))  # Pass by reference to C
print(p)                   # Uses __repr__() to print itself

输出:

Point(x=10, y=20)

相关问题