Python 错误的ctypes分配

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

我制作了一个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.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)