6

这是驻留在 DLL 中的 C 函数的原型:

extern "C" void__stdcall__declspec(dllexport) ReturnPulse(double*,double*,double*,double*,double*);

在另一个线程中,我询问了如何正确地创建和发送必要的参数给这个函数。

这是线程: 如何使用 ctypes 包装这个具有多个参数的 C 函数?

所以我在上面的线程中使用了很好的信息,但是现在我收到了这个错误:WindowsError: exception: access violation writing 0x00001001

我不确定如何进行。我使用的是 Windows XP - 如果我登录到管理员帐户,会解决问题吗?或者这是 Python 的内存对象不可变的问题?

谢谢大家!

用相关的 Python 编辑:

FROGPCGPMonitorDLL = windll.LoadLibrary('C:\Program Files\MesaPhotonics\VideoFROG 7.0\PCGPMonitor.dll')

#Function argument:double* pulse
sizePULSE = 2 ##Manual is super unclear here
pulse = c_double * sizePULSE
ptrpulse = pulse()

#Function argument:double* tdl
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE == 0 :
    sizeTRACE = 1 #Manually set size to 1 for testing purposes
    print "Size of FROG trace is zero. Probably not right."
tdl = c_double*sizeTRACE
ptrtdl = tdl()


#Function argument:double* tdP
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE==0:
    sizeTRACE=1
    print "Size of FROG trace is zero. Probably not right."
tdP = c_double*sizeTRACE
ptrtdP = tdP()


#Function Argument:double* fdl
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE==0:
    sizeTRACE=1
    print "Size of FROG trace is zero. Probably not right."
fdl = c_double*sizeTRACE
ptrfdl = fdl()

#Function Argument: double* fdP
sizeTRACE = FROGPCGPMonitorDLL.GetSize()
if sizeTRACE==0:
    sizeTRACE=1
    print "Size of FROG trace is zero. Probably not right."
fdP = c_double*sizeTRACE
ptrfdP = fdP()

FROGPCGPMonitorDLL.ReturnPulse(ptrpulse, ptrtdl, ptrtdP,ptrfdl,ptrfdP)

编辑添加一些相关代码!我只是在编写一个简单的脚本来让设备的每个功能首先工作。我知道,变量 sizeTRACE 可以重复使用,但它现在只是测试代码并且设备没有连接,所以 GetSize() 返回零。乘以零会扼杀我的嗡嗡声,所以我现在将其强制为 1。如果不清楚,我很抱歉,并会尝试编辑这篇文章。

第二次编辑:建议插入设备,看看是否有帮助。我刚刚插入了 FROG,但我仍然遇到同样的错误。很奇怪,我也很无知。无论如何,再次感谢大家!

4

2 回答 2

13

您收到的错误与管理权限无关。问题是您正在使用 C 并且无意中执行了非法操作(如果不加以检查,这种操作可能会使您的系统崩溃)。

您收到的错误表明您的程序正在尝试写入内存地址 1001,但不应该写入该内存地址。

这可能由于多种原因而发生。

一个可能的原因是您传递给 ReturnPulse 的 double* 没有 ReturnPulse 预期的那么大。您可能至少需要让 GetSize 正常工作......您可以通过分配一个非常大的数组而不是调用 GetSize 来解决它。IE

ptrfdP = (c_double*100000)()

这将分配 100,000 个双打,这可能更适合捕获数字脉冲。

另一个问题是类型转换可能没有按预期发生。

如果 ctypes 知道 ReturnPulse 需要五个双指针,您可能会有更好的运气。IE

# sometime before calling ReturnPulse
FROGPCGPMonitorDLL.ReturnPulse.argtypes = [POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double)]

如果这些技术都不起作用,请将使用文档发送到 ReturnPulse,这将有助于我们识别预期用途。

或者更好的是,发送应该在 C 中工作的示例代码,我会将其转换为 ctypes 中的等效实现。

编辑:添加 ReturnPulse 和 ctypes 用法的示例实现。

我已经实现了类似于我期望 ReturnPulse 在 C DLL 中执行的操作:

void ReturnPulse(double *a, double*b,double*c,double*d,double*e)
{
    // write some values to the memory pointed-to by a-e
    // a-e should have enough memory allocated for the loop
    for(int i = 0; i < 20; i++)
    {
        a[i] = 1.0*i;
        b[i] = 3.0*i;
        c[i] = 5.0*i;
        d[i] = 7.0*i;
        e[i] = 13.0*i;
    }
}

我将它编译成一个 DLL(我称之为examlib),然后使用 ctypes 和以下代码调用它:

LP_c_double = ctypes.POINTER(ctypes.c_double)
examlib.ReturnPulse.argtypes = [LP_c_double, LP_c_double, LP_c_double, LP_c_double, LP_c_double, ]

a = (ctypes.c_double*20)()
b = (ctypes.c_double*20)()
c = (ctypes.c_double*20)()
d = (ctypes.c_double*20)()
e = (ctypes.c_double*20)()

examlib.ReturnPulse(a,b,c,d,e)

print 'values are'
for array in (a,b,c,d,e):
    print '\t'.join(map(str, array[:5]))

结果输出是

values are
0.0     1.0     2.0     3.0     4.0
0.0     3.0     6.0     9.0     12.0
0.0     5.0     10.0    15.0    20.0
0.0     7.0     14.0    21.0    28.0
0.0     13.0    26.0    39.0    52.0

事实上,即使没有设置 ReturnPulse.argtypes,代码也可以正常运行。

于 2009-09-10T03:18:18.723 回答
0

ptrpulse 和朋友是指向各种 ctypes 对象的 python 标识符(我猜它们都是 c_double*2)。它们要么需要用 ctypes 指针对象包装,要么使用 ctypes.byref 传递给 C 函数。

于 2010-01-19T14:13:07.250 回答