在python中使用msl-loadlib封装c++库



我目前正在为一个c++库编写一个包装器。该库是一个32位的dll文件,我使用64位,所以我使用msl-loadlib。我在包装一个有指针形参的函数时遇到了问题。

下面是c++

函数的头文件
int CUSB::GetMeasurement(int Group, int StartPoint, int* NumberOfPoints, double* XData, double** YData, eFilter Filter)

这里我写了

from msl.loadlib import Server32
import ctypes
from client import Client
class Server(Server32):
def __init__(self, host: str, port: int):
super().__init__("USBLib.dll", "cdll", host, port)
...
def getMeasurement(self, group: int, startPoint: int, nbrOfPoints: int, filter: Client.Filter):
self.lib.GetMeasurement.restype = int
xData = (ctypes.c_double * 65536)()
yData = ((ctypes.c_double * 3) * 65536)()
self.lib.GetMeasurement(
ctypes.c_int(int(group)),
ctypes.c_int(int(startPoint)),
ctypes.pointer(ctypes.c_int(int(nbrOfPoints))),
ctypes.byref(xData),
ctypes.byref(yData),
ctypes.c_int(int(filter.value[0]))
)
return xData, yData
from enum import Enum, unique
from msl.loadlib import Client64
class Client(Client64):
@unique
class Filter(Enum):
NONE = 0,
LOWPASS = 1
...
def getMeasurement(self, group: int, startPoint: int, nbrOfPoints: int, filter: Filter):
return self.request32(
'getMeasurement',
group,
startPoint,
nbrOfPoints,
filter
)

当我叫Client.getMeasurement(parameters),我得到以下错误

File 'C:\Users\DELL\Documents\python\USBlib\server.py', line 77, in getMeasurement
ctypes.c_int(int(filter.value[0]))
OSError: exception: access violation writing 0x00000000

编辑:

我尝试使用ctypes .

xData = (ctypes.c_double * 65536)()
yData = ((ctypes.c_double * 3) * 65536)()
nbrOfPoints = ctypes.c_int()
self.lib.GetMeasurement.argtypes = [
ctypes.c_int,
ctypes.c_int,
ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_double),
ctypes.POINTER(ctypes.POINTER(ctypes.c_double)),
ctypes.c_int
]
dataSize = ctypes.c_int(int(inputDataSize - previousPoint))
self.lib.GetMeasurement(1, previousPoint, ctypes.byref(dataSize), xData, yData, Client.Filter.NONE)        

我有一个c++示例代码,使用GetMeasurement函数:

int PreviousPoint = 0;
double* ppYData1[3];
double* pXData1;
int UpdateSize = 65536;
for (int channel=0; channel<3; channel++)
{
ppYData1[channel] = new double[UpdateSize];
}
pXData1 = new double[UpdateSize];
int DataSize = Input1DataSize-PreviousPoint;
GetMeasurement(INPUT1, PreviousPoint, &DataSize, pXData1, ppYData1, (eFilter)(TC->SC->m_ScanConfiguration.m_nFilter));

我忽略了msl-loadlib,因为它与正确调用ctypes的问题无关。

这是调用函数的一个例子。YData需要是一个3 double*的数组,然后每个指针都需要用数组的下一个维度初始化。注意,这与调用函数的c++示例相似。

test.cpp-填写数组的示例实现。

#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif
typedef int eFilter;
extern "C" {
API int GetMeasurement(int Group, int StartPoint, int* NumberOfPoints, double* XData, double** YData, eFilter Filter) {
for(int i = 0; i < 65536; ++i) {
XData[i] = i;
YData[0][i] = i + .25;
YData[1][i] = i + .5;
YData[2][i] = i + .75;
}
return 0;
}
}

test.py- ctypes的例子调用函数

import ctypes as ct
pdouble = ct.POINTER(ct.c_double)
ppdouble = ct.POINTER(pdouble)
dll = ct.CDLL('./test')
dll.GetMeasurement.argtypes = ct.c_int, ct.c_int, ct.POINTER(ct.c_int), pdouble, ppdouble, ct.c_int
dll.GetMeasurement.restype = ct.c_int
xData = (ct.c_double * 65536)()
yData = (pdouble * 3)()
for channel in range(3):
yData[channel] = (ct.c_double * 65536)()
nbrOfPoints = ct.c_int()
dll.GetMeasurement(1, 0, ct.byref(nbrOfPoints), xData, yData, 0)
print(xData[0],xData[65535])
print(yData[0][0],yData[1][0],yData[2][0])
print(yData[0][65535],yData[1][65535],yData[2][65535])

输出:

0.0 65535.0
0.25 0.5 0.75
65535.25 65535.5 65535.75

最新更新