以下是驻留在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,但我仍然得到同样的错误。很奇怪,我很无能为力。无论如何,再次感谢所有人!
答案 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函数。