6

我正在使用 Python 的 ctypes 库与 Windows DLL 对话。当我从 IDLE、Ipython 运行我的代码或键入交互式 python 解释器时,它工作正常。当我从 Windows 命令提示符运行相同的代码时,它会崩溃。为什么一种方式崩溃,一种方式成功?

这是我正在运行的代码的简化版本:

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]

当我从 IDLE 或 Ipython 运行此代码时,我得到以下结果:

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

当我从 Windows 命令提示符运行此代码时,我得到以下结果:

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>

请注意,一些 DLL 调用可以正常工作,直到我开始设置传感器格式,我们才偏离了轨道。

通过检查我正在调用的 DLL 附带的文档,我看到 Windows 错误解码为“缓冲区的 wSize 太小”。(原文如此)。我不确定这是否相关。以防万一,这里是 API 文档

当我看到“在 IDLE 中工作,提示失败”时,我认为必须有一些不同的环境变量设置。我应该检查什么?

编辑:

我将 sys.path 和 os.getcwd() 添加到测试代码中。

编辑:

不确定这是否重要,但我加载的 DLL (SC2_Cam.dll) 位于当前工作目录中。此目录中还有另一个 DLL (sc2_cl_me4.dll),我相信它是由 SC2_Cam.dll 加载的。如果我从该目录中删除 sc2_cl_me4.dll,则对 SC2_Cam.dll 的调用都不起作用,包括 PCO_OpenCamera。

编辑:

如果我将上面的代码输入到“vanilla”交互式 python 解释器中,上面的代码也可以工作。我不需要 IDLE 或 ipython 来使其工作。仅调用“python.exe test.py”失败。

4

3 回答 3

5

你的系统上安装了多个版本的 python 吗?当您以交互方式运行和从文件运行它时,您可能正在使用不同的版本。

于 2012-05-13T02:15:37.120 回答
4

当您与 C 程序交互时,您会遇到 C 的所有困难。您犯的任何错误都可能导致缓冲区溢出、堆栈溢出、分段违规等。如果程序由于错误而写入随机内存位置,它的行为不会在所有情况下都相同。在您的机器上,它似乎在交互模式下工作,但从窗口命令提示符运行时会崩溃。但是在另一个操作系统上,或者在另一台机器上,甚至在另一天在同一台机器上,它的行为可能会有所不同。它的行为不是确定性的。

鉴于此,让我们看一下以下行:

PCO_api.PCO_OpenCamera(ctypes.byref(camera_handle), 0)

根据 API 文档,在上面的调用中,PCO_OpenCamera函数不只是返回一个值camera_handle;它也camera_handle用作输入值。但是,您camera_value未初始化。我了解您应该在通话前将其设置为零。另一个问题是PCO_OpenCamera返回一个应该检查的值。如果有问题但程序继续运行,就好像没有问题一样,它将继续使用随机值作为camera_handle. 所以程序中的一个错误似乎是前一行(保存打印)应该是

camera_handle = ctypes.c_ulong(0)

PCO_OpenCamera另一个是没有检查的返回值。(我不知道其余的是否还可以,我没有仔细检查过。)

此外,c_ulongWindowsHANDLE类型是否正确?不知道,应该没问题。即使c_ulong大于HANDLE,它仍然可能没问题。但可能还不够;你必须确定你知道你在做什么。

于 2012-05-15T15:43:37.250 回答
1

你得到的错误让我相信你用来存储 wSensor 变量的 16 位整数太小了。我查看了他们的 API,它只是将其指定为 WORD 类型,从历史上看,按照 Microsoft 的标准应该是 16 位,但由于单词的大小存在很多歧义,请尝试将值提高到 32 或 64 位。

至于为什么这会在不同的环境中导致不同的行为,您使用的是 64 位操作系统吗?你安装了不同版本的python吗?

于 2012-05-13T02:36:13.057 回答