"WindowsError: exception: access violation..." - ctypes question

trayres picture trayres · Sep 5, 2009 · Viewed 25.4k times · Source

Here is the prototype for a C function that resides in a DLL:

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

In another thread, I asked about how to properly create and send the necessary arguments to this function.

Here is the thread: How do I wrap this C function, with multiple arguments, with ctypes?

So I have used the good information in the thread above, but now I am getting this error: WindowsError: exception: access violation writing 0x00001001

I am unsure as to how to proceed. I'm on Windows XP - if I log into the administrator account, would that fix the problem? Or is this a problem with Python's memory objects being immutable?

Thanks all!

Edited with relevant 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)

Edited to add some relevant code! I'm just writing a simple script to get each of the device's functions working first. The variable sizeTRACE can be reused, I know, but its just test code right now and the device isn't hooked up, so GetSize() is returning zero. Multiplying by zero would kill my buzz, so I'm forcing it to 1 for now. If this isn't clear, I apologize and will try to edit this post.

Second edit: It was suggested to plug in the device and see if that helped. I just plugged in the FROG, but I'm still getting the same error. Very strange, and I'm rather clueless. In any event, thanks again all!

Answer

Jason R. Coombs picture Jason R. Coombs · Sep 10, 2009

The error you're getting is not related to Administrative rights. The problem is you're using C and inadvertently performing illegal operations (the kind of operations that if went unchecked would probably crash your system).

The error you get indicates that your program is trying to write to memory address 1001, but isn't supposed to be writing to that memory address.

This could happen for any number of reasons.

One possible reason is that the double* you're passing to ReturnPulse aren't as big as ReturnPulse expects them to be. You probably need to at least get GetSize to work properly... you might be able to work around it by just allocating a very large array instead of calling GetSize. i.e.

ptrfdP = (c_double*100000)()

That will allocate 100,000 doubles, which may be more appropriate for capturing a digital Pulse.

The other issue is that the type conversion may not be happening as expected.

You might have better luck if ctypes knows that ReturnPulse takes five double pointers. i.e.

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

If neither of these techniques works, send the usage documentation on ReturnPulse, which should help us recognize the intended use.

Or better yet, send sample code that's supposed to work in C and I'll translate that to the equivalent implementation in ctypes.

Edit: adding example implementation of ReturnPulse and ctypes usage.

I have implemented something like what I expect ReturnPulse to be doing in a 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;
    }
}

I compile this into a DLL (which I call examlib), and then call it using ctypes with the following code:

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]))

The resulting output is

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

Indeed, even without setting ReturnPulse.argtypes, the code runs without errors.