Python ctypes如何传递字符串和数组参数

时间:2017-06-19 21:38:12

标签: python excel vba numpy ctypes

我有一个可用的各种函数的dll,以及它在Excel VBA中使用的示例。我试图从python中调用DLL。

以下是我试图在Python中使用的Excel VBA中的函数声明:

Declare PtrSafe Function readparameter Lib "DATAREADER" Alias "__readparameter@32" (ByRef hfile As Long, ByVal parmname As String, ByRef tstart As Double, ByRef tstop As Double, ByRef htref As Long, ByRef time As Single, ByRef data As Single, ByRef npoints As Long) As Long

Excel中的函数调用如下所示:

hparm = readparameter(hfile, pidname, starttim, stoptime, htref, time(1), data(1), npoints)

...其中每个参数都是声明中指明的类型。时间和数据是1-D单阵列。

文档包含以下信息:

    readparameter(hfile,parmname,starttime,stoptime,htref,timearry,dataarry,npoints) - Retrieves parameter data from selected file
        Arguments:
            integer*4 hfile, input, a valid handle to a file structure (as returned by opendatafile())
            character*256 parmname, input, string buffer containing the parameter to be retrieved.
            real*8, starttime, input, starting time of data retreival (relative to htref, if used).
            real*8, stoptime, input, ending time of data retrieval (relative to htref, if used).
            integer*4 htref, input, handle to a data structure representing a t-zero reference point (can be 0).
            real*4 timearry(), output, data array to contain time stamps of retrieved data (size defined by npoints).
            real*4 dataarry(), output, data array to contain values of retrieved parameter data (size defined by npoints).
            integer*4 npoints, input+output, on input defines the size of timearry and dataarry, on output defines the number of points returned.
        Returns:
            0 on fail, else handle to parameter data structure (to be used by other functions).

到目前为止,我已将以下脚本拼凑在一起:

import os
import numpy as np
from numpy.ctypeslib import ndpointer
import ctypes
from ctypes import cdll, CDLL, WinDLL
from ctypes import *

libpath = r'D:\DataReader'
libname = r'DataReader.dll'

os.environ['PATH'] = os.environ['PATH'] + ';' + libpath + '\\'

EasyRead = cdll.LoadLibrary('DATAREADER')

filename = ctypes.create_string_buffer(b'D:\test.dat')

hfile = DataRead.opendatafile(filename)
pidname = ctypes.create_string_buffer(b'sine', 256)
starttime = 0.0
stoptime = 10.0
timedelta = 1
htref = 0
npoints = 1000
time_np = np.zeros(npoints, np.double)
data_np = np.zeros(npoints, np.double)
make_array_pointer = lambda x: (x.ctypes.data + np.arange(x.shape[0]) * x.strides[0]).astype(np.uintp)
time_c = make_array_pointer(time_np)
data_c = make_array_pointer(data_np)
double_type = np.ctypeslib.ndpointer(dtype=np.uintp)

DataReader.readparameter.argtypes = [ctypes.c_long, ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_long, double_type, double_type, ctypes.c_long]

hparm = DataReader.readparameter(hfile, pidname, starttime, stoptime, htref, time_c, data_c, npoints)

...导致OS Error: exception: access violation reading 0x00000000

我不确定我是否正确设置了参数及其数据类型。在VBA声明中,看起来声明只是在常见的VBA数据类型中进行,然后直接传递那些本机VBA变量。我如何恰当地告诉ctypes我想传递哪些Python / numpy类型?这甚至是问题吗?我在使用C数据类型时非常缺乏经验,并且拼凑了来自各种Google搜索的ctypes内容,但是如果ctypes.c_char_p适合传入字符串,或者我是否正确地执行数组,那么我真的不明白。

任何帮助都会很棒。对不起,我无法共享DLL源代码。

0 个答案:

没有答案