Python 错误的ctypes分配
我制作了一个CPP DLL,并试图从python调用其中的函数。 我已经为其他函数实现了多次,但这一次,我就是找不到我的错误Python 错误的ctypes分配,python,c++,ctypes,dynamic-dll-import,Python,C++,Ctypes,Dynamic Dll Import,我制作了一个CPP DLL,并试图从python调用其中的函数。 我已经为其他函数实现了多次,但这一次,我就是找不到我的错误 dll_name = "..\\src\\x64\\Debug\\2019-3A-IBD-MLDLL.dll" dllabspath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + dll_name myDll = CDLL(dllabspath) #fit_reg_RBF_naive myDll
dll_name = "..\\src\\x64\\Debug\\2019-3A-IBD-MLDLL.dll"
dllabspath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + dll_name
myDll = CDLL(dllabspath)
#fit_reg_RBF_naive
myDll.fit_reg_RBF_naive.argtypes = [ct.c_void_p, ct.c_double, ct.c_void_p, ct.c_int, ct.c_int]
myDll.fit_reg_RBF_naive.restypes = ct.c_void_p
#predict_reg_RBF_naive
myDll.predict_reg_RBF_naive.argtypes = [ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_int, ct.c_double, ct.c_int]
myDll.predict_reg_RBF_naive.restypes = ct.c_double
def fit_reg_RBF_naive(pyXTrain, pyGamma, pyYTrain, pySampleCount, pyInputCountPerSample):
XTrain = (ct.c_double * len(pyXTrain))(*pyXTrain)
YTrain = (ct.c_double * len(pyYTrain))(*pyYTrain)
inputCountPerSample = ct.c_int(pyInputCountPerSample)
sampleCount = ct.c_int(pySampleCount)
gamma = ct.c_double(pyGamma)
return myDll.fit_reg_RBF_naive(XTrain, gamma, YTrain, sampleCount, inputCountPerSample)
def predict_reg_RBF_naive(pyW, pyXTrain, pyXpredict ,pyInputCountPerSample, pyGamma, pySampleCount):
XTrain = (ct.c_double * len(pyXTrain))(*pyXTrain)
inputCountPerSample = ct.c_int(pyInputCountPerSample)
sampleCount = ct.c_int(pySampleCount)
gamma = ct.c_double(pyGamma)
Xpredict = (ct.c_double * len(pyXpredict))(*pyXpredict)
return myDll.predict_reg_RBF_naive(W, XTrain, Xpredict, inputCountPerSample, gamma, sampleCount)
基本上,我加载我的DLL,为参数设置Ctypes,并为两个函数设置结果。然后我制作了一个python包装器,这样用户就不必重新键入从python到cpp的每个转换
我在cpp方面的类型似乎也不错:
extern "C" {
SUPEREXPORT double predict_reg_RBF_naive(double* W, double* X, double* Xpredict, int inputCountPerSample, double gamma, int N);
SUPEREXPORT double* fit_reg_RBF_naive(double* XTrain, double gamma, double* YTrain, int sampleCount, int inputCountPerSample);
}
对于cpp部分,我没有收到编译器的警告,我已经在cpp中的fit\u reg\u RBF\u naive
和python中的W
中打印了返回之前的内存地址,它们是相同的
000002B358384980 // cpp address of W before return
0x58384980 # Python address of W after function call
对我来说,似乎是同一个地址。也许我错了
所以当我尝试调用我的第二个cpp函数时,它说
myDll.predict\u reg\u RBF\u naive(W、XTrain、Xpredict、inputCountPerSample、gamma、sampleCount)
OS错误:异常:访问冲突读取0x000000007C7380A0
当它试图读取W
时,它在cpp中崩溃。它们在cpp中没有free
或“delete”,并且变量分配正确:double*W=newdouble[2]代码>
另外,当我打印W
时,我会得到
为什么我的W
在语言方面似乎有相同的地址,但没有好的类型?将fit\u reg\u RBF\u naive
的结果类型更改为指针(ct.c\u double*2)
不会进行任何更改
编辑:
以下是我如何调用我的函数:
from dll_load import predict_reg_RBF_naive, fit_reg_RBF_naive
gamma = 50
sampleCount = 2
inputCountPerSample = 3
XTrain = [1.0, 1.0, 1.0, 3.0, 3.0, 3.0]
YTrain = [-1.0, 1.0]
Xpredict = [1.0, 1.0, 1.0]
W = fit_reg_RBF_naive(XTrain, gamma, YTrain, sampleCount, inputCountPerSample)
print(predict_reg_RBF_naive(W, XTrain, Xpredict, inputCountPerSample, gamma, sampleCount))
您拼错了restypes(应该是restype)。这样做,restype不会初始化,默认为int(32位上不会有问题),您会遇到:
除此之外,代码中还有几个问题:
- 如果C函数指定了一个指针(
double*
,在这种情况下),不要使用ctypes.C\u void\u p
(在argtypes或restype中)来映射它,因为它可能太宽,请改用(在这种情况下)ctypes.pointer(ctypes.C\u double)
- 对我来说,这甚至不能编译(我想知道你是如何运行这段代码的)。我将仅在XTrain上举例说明,但也适用于YTrain和Xpredict。ctypes不知道如何将Python列表转换为
ctypes.POINTER(ctypes.c\u double)
(或ctypes.c\u void\u p
),必须手动进行转换(转换为ctypes.c\u double
数组):
并将xtrain_ctypes传递给函数
000002B35884980
和0x58384980
完全不同,第一个以2B
开头,然后又有八个数字,第二个只有最后八个数字。这是32位和64位错误的症状,尽管这些错误发生在哪里,我不能马上确定。我同意你的看法。但我不明白为什么这种现象存在,而我所有的其他函数似乎都是以同样的方式编码的。。。我将对你的想法大加赞赏。而且,那件事似乎可疑。您可能需要应用指针
,我已经有一段时间没有对ctypes
大惊小怪了。我同意您的看法W
应该是ct.c\u void\u p
关于myDll.fit\u reg\u RBF\u naive.restypes=ct.c\u void\u p
?。编辑:我将在中添加我的通话文件python@torek从我的DLL/python中的另一个函数中,我得到了与W
相同的类型
,我知道。。。只有一个打字错误。。。谢谢你,先生。对于输出类型,我不需要具体说明类型。有时我会将复杂的结构从DLL tp python再次传递到DLL。python为什么不给我关于这类错误的错误或警告?通常它会说“ImportError:没有名为restypes的模块”?我会将所有python变量转换为ctypes。我已经对列表进行了转换。我的代码看起来一团糟,因为我在python和cpp中使用了相同的名称。我同意这是令人困惑的。恐怖是一个完全不同的问题。Python允许您动态地向实例添加成员(这就是为什么不会出现错误)。我没有;Don’不要说代码很混乱。显然,这里缺少了一些部分:)。好的,谢谢你的评论,我不习惯python,我更喜欢C程序员。事实上,代码并不完整,读起来有点沉重。
XTrain = [1.0, 1.0, 1.0, 3.0, 3.0, 3.0]
xtrain_ctypes = (ctypes.c_double * len(XTrain))(*XTrain)