错误的 ctypes 分配
Wrong ctypes assignation
我制作了一个 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_reg_RBF_naive
中的 return 和 [=48 中的 W
之前打印了内存地址=] 并且它们是相同的。
000002B358384980 // cpp address of W before return
0x58384980 # Python address of W after function call
对我来说似乎是同一个地址。也许我错了。
所以当我尝试调用我的第二个 cpp 函数时它说
myDll.predict_reg_RBF_naive(W, XTrain, Xpredict,inputCountPerSample, gamma, sampleCount)
OSError: exception: access violation reading 0x000000007C7380A0
它在尝试读取 W
时在 cpp 中崩溃。它们在 cpp 中没有 free
或 'delete' 并且变量已正确分配:double* W = new double[2];
此外,当我打印 W
输入 python 时,我得到 <class 'int'>
.
我的W
怎么好像语言地址一样,但是类型不对?将 fit_reg_RBF_naive
的结果类型更改为 POINTER(ct.c_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))
[Python 3.Docs]: ctypes - A foreign function library for Python.
你拼错了restypes(应该是restype).通过这样做,restype 没有被初始化,并且默认为 int(这在 32bit),而你 运行 变成:
除此之外,代码中还有几个问题:
- 如果C函数指定了一个指针(在本例中为
double*
),不要使用ctypes.c_void_p
(在argtypes 或 restype) 来映射它,因为它可能太宽了,使用(对于这种情况)ctypes.POINTER(ctypes.c_double)
而不是
对我来说,这甚至不能编译(我想知道你是如何能够 运行 那个代码的)。我将仅在 XTrain 上举例说明,但 适用于 YTrain 和 Xpredict 还有。 ctypes 不知道将 Python 列表转换为 ctypes.POINTER(ctypes.c_double)
(或 ctypes.c_void_p
),并且必须手动进行转换(到 ctypes.c_double
数组):
XTrain = [1.0, 1.0, 1.0, 3.0, 3.0, 3.0]
xtrain_ctypes = (ctypes.c_double * len(XTrain))(*XTrain)
并将xtrain_ctypes传递给函数。
我制作了一个 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_reg_RBF_naive
中的 return 和 [=48 中的 W
之前打印了内存地址=] 并且它们是相同的。
000002B358384980 // cpp address of W before return
0x58384980 # Python address of W after function call
对我来说似乎是同一个地址。也许我错了。
所以当我尝试调用我的第二个 cpp 函数时它说
myDll.predict_reg_RBF_naive(W, XTrain, Xpredict,inputCountPerSample, gamma, sampleCount) OSError: exception: access violation reading 0x000000007C7380A0
它在尝试读取 W
时在 cpp 中崩溃。它们在 cpp 中没有 free
或 'delete' 并且变量已正确分配:double* W = new double[2];
此外,当我打印 W
输入 python 时,我得到 <class 'int'>
.
我的W
怎么好像语言地址一样,但是类型不对?将 fit_reg_RBF_naive
的结果类型更改为 POINTER(ct.c_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))
[Python 3.Docs]: ctypes - A foreign function library for Python.
你拼错了restypes(应该是restype).通过这样做,restype 没有被初始化,并且默认为 int(这在 32bit),而你 运行 变成:
除此之外,代码中还有几个问题:
- 如果C函数指定了一个指针(在本例中为
double*
),不要使用ctypes.c_void_p
(在argtypes 或 restype) 来映射它,因为它可能太宽了,使用(对于这种情况)ctypes.POINTER(ctypes.c_double)
而不是 对我来说,这甚至不能编译(我想知道你是如何能够 运行 那个代码的)。我将仅在 XTrain 上举例说明,但 适用于 YTrain 和 Xpredict 还有。 ctypes 不知道将 Python 列表转换为
ctypes.POINTER(ctypes.c_double)
(或ctypes.c_void_p
),并且必须手动进行转换(到ctypes.c_double
数组):XTrain = [1.0, 1.0, 1.0, 3.0, 3.0, 3.0] xtrain_ctypes = (ctypes.c_double * len(XTrain))(*XTrain)
并将xtrain_ctypes传递给函数。