在C中进行Mallocing和释放,但通过ctypes在Python中传递指针



我想在c中放置一个malloca函数,然后我想通过ctypes.DLL从Python 3.10调用这个函数。然后我想free它。

然而,我得到一个分割错误。下面是我非常简单的C代码:

#include <stdlib.h>
struct QueueItem {
void *value;
struct QueueItem *next;
};
struct Queue {
struct QueueItem* head;
struct QueueItem* tail;
};
struct Queue * new_queue(void * value) {
struct Queue* queue = malloc(sizeof(struct Queue));
struct Queue queue_ = { value, NULL };
return queue;
}
void delete_queue(struct Queue* queue) {
free(queue);
};

我将用gcc -fPIC -shared src/queue.c -o queue.so编译它,然后在python端:

import ctypes
queue = ctypes.CDLL("./queue.so")
q = ctypes.POINTER(queue.new_queue(1))
print(q)
print(type(q))
queue.delete_queue(q)

但是运行这个将产生:

-1529189344
<class 'int'>
Segmentation fault

问题是,如何在C中malloc,通过python传递指针,然后在C中再次释放它?.

Primary Resources consultation:

  • 在Python中通过Ctypes传递指针到DLL
  • Python Ctypes向包含void指针数组的结构传递指针
  • https://docs.python.org/3/library/ctypes.html
  • 乱搞ctypes。但是它抱怨类型,我不是这方面的专家。

如果您没有为函数定义restypeargtypes,则假定restype为Cint(c_int),并且根据您传递的内容猜测参数类型。这里的问题是int的隐式restype(在64位系统上)是指针宽度的一半,所以new_queue返回的值只是指针的一半(这是完全无用的)。

为了安全和错误检查,您应该在调用函数之前定义它们,特别是不能推断的restype

对于你的代码,你可以这样写:

import ctypes
queue = ctypes.CDLL("./queue.so")
queue.new_queue.argtypes = (c_void_p,)
queue.new_queue.restype = c_void_p
queue.delete_queue.argtypes = (c_void_p,)
queue.delete_queue.restype = None
q = queue.new_queue(1)
print(q)
print(type(q))
queue.delete_queue(q)

请注意,将1作为参数传递给new_queue几乎肯定是不正确的,但我怀疑它会在这里工作,因为没有代码会实际尝试使用它。

最新更新