“WindowsError:异常:访问冲突......” - ctypes问题

时间:2009-09-05 00:35:26

标签: python ctypes access-violation windowserror

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

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

在另一个主题中,我询问了如何正确创建并向该函数发送必要的参数。

以下是主题: How do I wrap this C function, with multiple arguments, with ctypes?

所以我在上面的线程中使用了很好的信息,但现在我收到了这个错误: WindowsError:exception:访问冲突写入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,但我仍然得到同样的错误。很奇怪,我很无能为力。无论如何,再次感谢所有人!

2 个答案:

答案 0 :(得分:12)

您获得的错误与管理权限无关。问题是你正在使用C并且无意中执行了非法操作(如果取消选中的那种操作可能会导致系统崩溃)。

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

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

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

ptrfdP = (c_double*100000)()

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

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

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

# 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,代码也可以正常运行。

答案 1 :(得分:0)

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