这是我的 C 代码:
typedef struct {
int a;
}A;
__declspec(dllexport) A new_a(int x) {
A a = {x};
return a;
}
__declspec(dllexport) void change(A a) { a.a++; }
__declspec(dllexport) int get_a (A a) { return a.a; }
我将它编译成一个 MODULE DLL,在 Python 中我这样做了:
import ctypes
lib = ctypes.windll.LoadLibrary('C:\\Users\\avishah\\CLionProjects\\Math\\lib\\libpythonclass2.dll')
a = lib.new_a(10)
print(lib.get_a(a), type(a)) # gives 10, says type of a is 'int'
lib.change(a) # doesn't change value
print(lib.get_a(a)) # still shows 10
我确定我必须在 C 代码中使用指针,但它通常给我这个错误:
OSError: exception: access violation reading 0x000000000000000A
您的代码有两个问题。
第一个是您没有为您导入的 FFI 函数指定类型签名。您需要为您的结构创建类型定义,并将参数和返回类型分配给导入的函数。
import ctypes
lib = ctypes.windll.LoadLibrary(r'C:\Users\avishah\CLionProjects\Math\lib\libpythonclass2.dll')
class A(ctypes.Structure):
_fields_ = (
('a', ctypes.c_int),
)
new_a = lib.new_a
new_a.restype = A
new_a.argtypes = (ctypes.c_int,)
change = lib.change
change.restype = None
change.argtypes = (A,)
get_a = lib.get_a
get_a.restype = ctypes.c_int
get_a.argtypes = (A,)
二是change
函数按值接收结构体。换句话说,该函数对参数列表上接收到的结构的副本进行操作,这意味着调用者持有的副本永远不会被修改。要实际修改结构,您需要传递一个指针:
__declspec(dllexport) void change(A *a) { a->a++; }
change = lib.change
change.restype = None
change.argtypes = (ctypes.POINTER(A),)
现在您的代码应该如您所愿:
a = new_a(10)
print(get_a(a), type(a)) # should print 10 <class '__main__.A'>
change(ctypes.byref(a)) # equivalent C: change(&a);
print(get_a(a)) # should print 11
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句