从 ctypes 回调到 return 的正确指针类型是什么?
What is the correct pointer type to return from a ctypes callback?
我有一个 ctypes 回调,它从 dll 中获取一个指向两个双精度的指针,returns 一个指向两个双精度的指针返回到 .dll。第一部分工作正常,但经过大量测试和研究,我仍然无法在回调后获得指向 .dll 的 return 的正确指针。
这是 ctypes 回调代码:
from scipy.integrate import dblquad
import ctypes
LibraryCB = ctypes.WINFUNCTYPE(ctypes.py_object, ctypes.POINTER(ctypes.c_double))
def LibraryCall(ptr):
n = ctypes.cast(ptr,ctypes.POINTER(ctypes.c_double))
x = n[0] #Value = 83.0
y = n[1] #Value = 30.0
area = dblquad(lambda x, y: x*y, 0, 0.5, lambda x: 0, lambda x: 1-2*x)
return_val = area[0], area[1]
return (return_val)
lib_call = LibraryCB(LibraryCall)
lib_call = ctypes.cast(lib_call,ctypes.POINTER(ctypes.c_longlong))
我使用 ctypes.py_object 作为指向 return 的指针类型,因为所有其他指针类型 return 一个错误,它不是回调的有效指针类型。
指向dll的指针return,但提取的值不匹配,这表明我没有正确的指针类型。
我还尝试将 return 值转换为这样的指针:rv = ctypes.cast(return_val,ctypes.POINTER(ctypes.c_double)),并 returning 那个,但是那没有用。
这里是调用dll和回调的相关ctypes代码:
CA_data1 = (ctypes.c_double * len(data1))(*data1)
CA_data2 = (ctypes.c_double * len(data2))(*data2)
hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/SciPy_Test/SciPy_Test.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_longlong)]
CallName.restype = ctypes.c_double
ret_ptr = CallName(CA_data1,CA_data2,length_array_out,lib_call)
非常感谢您提供有关如何解决此问题的任何想法。
DLL 代码必须直接处理 Python 个对象。您不能简单地将 Python 对象转换为 ctypes 指针。如果可以更改 DLL 代码,最简单的方法是使用 input/output 参数:
test.c
#include <stdio.h>
typedef void (*CALLBACK)(double*);
__declspec(dllexport) void function(CALLBACK callback)
{
double param[2] = {1.5, 2.5};
callback(param);
printf("%lf %lf\n",param[0],param[1]);
}
test.py
from ctypes import *
CALLBACK = PYFUNCTYPE(None,POINTER(c_double))
@CALLBACK
def LibraryCB(data):
x = data[0]
y = data[1]
print(x,y)
data[0] *= 2
data[1] *= 2
dll = CDLL('test')
dll.function.argtypes = [CALLBACK]
dll.function.restype = None
cb = CALLBACK(LibraryCB)
dll.function(cb)
输出
1.5 2.5
3.000000 5.000000
我有一个 ctypes 回调,它从 dll 中获取一个指向两个双精度的指针,returns 一个指向两个双精度的指针返回到 .dll。第一部分工作正常,但经过大量测试和研究,我仍然无法在回调后获得指向 .dll 的 return 的正确指针。
这是 ctypes 回调代码:
from scipy.integrate import dblquad
import ctypes
LibraryCB = ctypes.WINFUNCTYPE(ctypes.py_object, ctypes.POINTER(ctypes.c_double))
def LibraryCall(ptr):
n = ctypes.cast(ptr,ctypes.POINTER(ctypes.c_double))
x = n[0] #Value = 83.0
y = n[1] #Value = 30.0
area = dblquad(lambda x, y: x*y, 0, 0.5, lambda x: 0, lambda x: 1-2*x)
return_val = area[0], area[1]
return (return_val)
lib_call = LibraryCB(LibraryCall)
lib_call = ctypes.cast(lib_call,ctypes.POINTER(ctypes.c_longlong))
我使用 ctypes.py_object 作为指向 return 的指针类型,因为所有其他指针类型 return 一个错误,它不是回调的有效指针类型。
指向dll的指针return,但提取的值不匹配,这表明我没有正确的指针类型。
我还尝试将 return 值转换为这样的指针:rv = ctypes.cast(return_val,ctypes.POINTER(ctypes.c_double)),并 returning 那个,但是那没有用。
这里是调用dll和回调的相关ctypes代码:
CA_data1 = (ctypes.c_double * len(data1))(*data1)
CA_data2 = (ctypes.c_double * len(data2))(*data2)
hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/SciPy_Test/SciPy_Test.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_longlong)]
CallName.restype = ctypes.c_double
ret_ptr = CallName(CA_data1,CA_data2,length_array_out,lib_call)
非常感谢您提供有关如何解决此问题的任何想法。
DLL 代码必须直接处理 Python 个对象。您不能简单地将 Python 对象转换为 ctypes 指针。如果可以更改 DLL 代码,最简单的方法是使用 input/output 参数:
test.c
#include <stdio.h>
typedef void (*CALLBACK)(double*);
__declspec(dllexport) void function(CALLBACK callback)
{
double param[2] = {1.5, 2.5};
callback(param);
printf("%lf %lf\n",param[0],param[1]);
}
test.py
from ctypes import *
CALLBACK = PYFUNCTYPE(None,POINTER(c_double))
@CALLBACK
def LibraryCB(data):
x = data[0]
y = data[1]
print(x,y)
data[0] *= 2
data[1] *= 2
dll = CDLL('test')
dll.function.argtypes = [CALLBACK]
dll.function.restype = None
cb = CALLBACK(LibraryCB)
dll.function(cb)
输出
1.5 2.5
3.000000 5.000000