I’m using Python’s ctypes library to talk to a Windows DLL. When I run my code from IDLE, Ipython, or typed into the interactive python interpreter, it works fine. When I run the same code from the Windows command prompt, it crashes. Why does one way crash, and one way succeed?
Here’s a simplified version of the code I’m running:
import ctypes, os, sys
print "Current directory:", os.getcwd()
print "sys.path:"
for i in sys.path:
print i
PCO_api = ctypes.oledll.LoadLibrary("SC2_Cam")
camera_handle = ctypes.c_ulong()
print "Opening camera..."
PCO_api.PCO_OpenCamera(ctypes.byref(camera_handle), 0)
print " Camera handle:", camera_handle.value
wSensor = ctypes.c_uint16(0)
print "Setting sensor format..."
PCO_api.PCO_SetSensorFormat(camera_handle, wSensor)
PCO_api.PCO_GetSensorFormat(camera_handle, ctypes.byref(wSensor))
mode_names = {0: "standard", 1:"extended"}
print " Sensor format is", mode_names[wSensor.value]
When I run this code from IDLE or Ipython, I get the following result:
Current directory: C:\Users\Admin\Desktop\code
sys.path:
C:\Users\Admin\Desktop\code
C:\Python27\Lib\idlelib
C:\Windows\system32\python27.zip
C:\Python27\DLLs
C:\Python27\lib
C:\Python27\lib\plat-win
C:\Python27\lib\lib-tk
C:\Python27
C:\Python27\lib\site-packages
Opening camera...
Camera handle: 39354336
Setting sensor format...
Sensor format is standard
>>>
When I run this code from the Windows command prompt, I get the following results:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\Admin>cd Desktop\code
C:\Users\Admin\Desktop\code>C:\Python27\python.exe test.py
Current directory: C:\Users\Admin\Desktop\code
sys.path:
C:\Users\Admin\Desktop\code
C:\Windows\system32\python27.zip
C:\Python27\DLLs
C:\Python27\lib
C:\Python27\lib\plat-win
C:\Python27\lib\lib-tk
C:\Python27
C:\Python27\lib\site-packages
Opening camera...
Camera handle: 43742176
Setting sensor format...
Traceback (most recent call last):
File "test.py", line 18, in <module>
PCO_api.PCO_GetSensorFormat(camera_handle, ctypes.byref(wSensor))
File "_ctypes/callproc.c", line 936, in GetResult
WindowsError: [Error -1609945086] Windows Error 0xA00A3002
C:\Users\Admin\Desktop\code>
Notice that a few of the DLL calls work, it isn’t until I get to setting the sensor format that we go off the rails.
By inspecting the documentation that came with the DLL I’m calling, I see the Windows Error decodes to “The wSize of a buffer is to small.” (sic). I’m not sure that’s relevant. Just in case it matters, here’s the API documentation.
When I see “works in IDLE, fails at prompt”, I assume there must be some environment variable set differently. What should I check?
EDIT:
I added sys.path and os.getcwd() to the test code.
EDIT:
Not sure if this matters, but the DLL I load (SC2_Cam.dll) is in the current working directory. Also in this directory is another DLL (sc2_cl_me4.dll), which I believe is loaded by SC2_Cam.dll. If I remove sc2_cl_me4.dll from this directory, none of the calls to SC2_Cam.dll work, including PCO_OpenCamera.
EDIT:
The code above also works if I type it into the ‘vanilla’ interactive python interpreter. I don’t need IDLE or ipython to make it work. Only calling ‘python.exe test.py’ fails.
When you interface with a C program, you get all the difficulties of C. Any error you make can cause buffer overflows, stack overflows, segmentation violations, etc. If the program, because of an error, writes to a random memory location, its behavior will not be the same in all circumstances. On your machine, it seems to work in interactive mode, but crashes when run from the window command prompt. But on another operating system, or on another machine, or even in the same machine in another day, it could behave differently. Its behavior is not deterministic.
Given that, let’s look at the following line:
According to the API documentation, in the above call, the
PCO_OpenCamerafunction does not just return a value incamera_handle; it also usescamera_handleas an input value. However, you leavecamera_valueuninitialized. I understand that you should set it to zero before the call. Another problem is thatPCO_OpenCamerareturns a value which should be checked. If there is a problem but the program continues as if there wasn’t, it will continue to use a random value for thecamera_handle. So one error in the program seems to be that the preceding line (save the print) should beand another is that the return value of
PCO_OpenCameraisn’t checked. (I don’t know if the rest is OK, I haven’t examined carefully past that.)Also, is
c_ulongthe proper type for the WindowsHANDLEtype? I don’t know, and it may be ok. Even ifc_ulongis larger thanHANDLE, it’s still probably OK. But probably is not enough; you must be certain that you know what you’re doing.