I made a CPP DLL and I'm trying to call function inside it from python. I've achieved this multiple times for other functions, but this one, I just can't find my mistake.
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)
Basically I load my DLL, set Ctypes for arguments and result for both of my fonctions. Then I make a python wrapper so that the user does not have to retype every cast from python to cpp.
My types on the cpp side seems good too:
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);
}
I have no warning from the compiler for the cpp part, I've printed the memory adresse before the return inside fit_reg_RBF_naive from cpp and the W in python and they are the same.
000002B358384980 // cpp address of W before return
0x58384980 # Python address of W after function call
For me it seems the same address. Maybe I'm wrong.
So when I try to call my second cpp function it said
myDll.predict_reg_RBF_naive(W, XTrain, Xpredict,inputCountPerSample, gamma, sampleCount) OSError: exception: access violation reading 0x000000007C7380A0
It crashed in the cpp when it tries to read W. They are no free or 'delete' in the cpp and the variable is properly allocated : double* W = new double[2];
Also, when I print W type in python I get <class 'int'>.
How comes my W seems to have the same address regarding the language, but has not the good type? Changing the result type of fit_reg_RBF_naive to POINTER(ct.c_double * 2) makes no change.
EDIT:
Here is how I call my functions:
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))
000002B358384980and0x58384980are not the same at all, the first starts with2Band then has eight more digits and the second has only the final eight digits. This is symptomatic of 32 vs 64 bit errors, though where those errors are occurring I'm not sure off hand.<class 'int'>thing seems suspicious. You may wantPOINTERapplied, it's been a while since I fussed withctypes.Wshould bect.c_void_pregardingmyDll.fit_reg_RBF_naive.restypes = ct.c_void_p?. Edit: I'll add my call file in python<class 'int'>forW