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

tra*_*res 5 python ctypes windowserror access-violation

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

extern "C" void__stdcall__declspec(dllexport) ReturnPulse(double*,double*,double*,double*,double*);
Run Code Online (Sandbox Code Playgroud)

在另一个线程中,我询问了如何正确创建并向此函数发送必要的参数.

这是一个主题: 如何用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)
Run Code Online (Sandbox Code Playgroud)

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

第二次编辑:有人建议插入设备,看看是否有帮助.我只是插入了FROG,但我仍然得到同样的错误.很奇怪,我很无能为力.无论如何,再次感谢所有人!

Jas*_*mbs 12

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

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

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

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

ptrfdP = (c_double*100000)()
Run Code Online (Sandbox Code Playgroud)

这将分配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)]
Run Code Online (Sandbox Code Playgroud)

如果这些技术都不起作用,请在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我把它编译成一个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]))
Run Code Online (Sandbox Code Playgroud)

结果输出是

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
Run Code Online (Sandbox Code Playgroud)

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