我想在c中放置一个malloc
a函数,然后我想通过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。但是它抱怨类型,我不是这方面的专家。
如果您没有为函数定义restype
和argtypes
,则假定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
几乎肯定是不正确的,但我怀疑它会在这里工作,因为没有代码会实际尝试使用它。