Skip to main content
 首页 » 编程设计

python之在 python 中使用 ctypes 从 .so 文件链接时出现奇怪的改变行为

2025年05月04日8yxwkf

我正在为我的博士学位编写一个程序来处理来自高速相机的数据。项目。这个摄像头在 Linux 上以 .so 文件的形式附带一个 SDK,用于与摄像头通信并获取图像。正如所说,它是一种提供大量数据(每分钟几 GB)的高速相机。为了处理如此大量的数据,SDK 有一个非常方便的假脱机功能,可以通过 DMA 将数据以 FITS 文件的形式直接假脱机到硬盘驱动器,这是一种带有用于天文学的 header 的原始二进制格式。 当我编写一个小的 C 程序、链接 .so 文件并以这种方式调用假脱机函数时,此函数工作正常。但是当我用 ctypes 包装 .so 文件并从 python 调用函数时,所有函数都在工作,除了 spool 函数。当我调用假脱机函数时,它没有返回任何错误,但假脱机数据文件出现乱码,文件格式正确,但所有帧中有一半为 0。 在我的世界里,.so 文件中的函数应该根据从哪个程序调用而表现不同是没有意义的,我自己的小 C 程序或 python 毕竟只是一个更大的 C 程序。有没有人知道从不同程序调用 .so 时有什么不同?

如果有任何建议,我将不胜感激

尽管相机是商用的,但有些驱动程序是 GPL 的并且可用,尽管有点复杂。 (不幸的是,它似乎不是假脱机功能)我在 python 中有一个用于 Handel 相机的对象。

类(class)的开头是:

class Andor: 
  def __init__(self,handle=100): 
    #cdll.LoadLibrary("/usr/local/lib/libandor.so") 
    self.dll = CDLL("/usr/local/lib/libandor.so") 
error = self.dll.SetCurrentCamera(c_long(handle)) 
    error = self.dll.Initialize("/usr/local/etc/andor/") 
 
    cw = c_int() 
    ch = c_int() 
    self.dll.GetDetector(byref(cw), byref(ch)) 

相关函数如下:

def SetSpool(self, active, method, path, framebuffersize): 
    error = self.dll.SetSpool(active, method, c_char_p(path), framebuffersize) 
    self.verbose(ERROR_CODE[error], sys._getframe().f_code.co_name) 
    return ERROR_CODE[error] 

在相应的标题中,它显示为:

unsigned int SetSingleTrackHBin(int bin); 
 
unsigned int SetSpool(int active, int method, char * path, int framebuffersize); 
 
unsigned int SetStorageMode(at_32 mode); 
 
unsigned int SetTemperature(int temperature); 

让相机运行的代码应该是这样的:

cam = andor.Andor() 
cam.SetReadMode(4) 
cam.SetFrameTransferMode(1) 
cam.SetShutter(0,1,0,0) 
cam.SetSpool(1,5,'/tmp/test.fits',10); 
cam.GetStatus() 
if cam.status == 'DRV_IDLE': 
acquireEvent.clear() 
cam.SetAcquisitionMode(3) 
cam.SetExposureTime(0.0) 
cam.SetNumberKinetics(exposureNumber) 
cam.StartAcquisition() 

请您参考如下方法:

我的猜测是,这不是对假脱机函数本身的调用,而是导致向库输入/从库输入损坏值的调用序列。

您使用的是 64 位平台吗?不为任何返回 64 位整数(long 与 gcc)或指针指定 restype 将导致这些值被静默截断为 32 位。此外,ctypes.c_voidp 处理有点令人惊讶 — ctypes.c_voidp 的 restype 值没有被截断,而是在 Python 解释器中返回作为 int 类型,如果高指针在没有转换的情况下作为参数反馈给其他函数,结果会很滑稽。

我还没有测试过,但是对于大于 sys.maxint 的值,这两种情况也可能影响 32 位平台。

要 100% 确定您正在传递和接收您期望的值的唯一方法是为您调用的所有函数指定 argtypes 和 restype。这包括为这些函数运行的所有 struct 创建 Structure 类和关联的 POINTER,甚至是不透明的 struct