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

在python中使用ctypes从.so文件链接时,奇怪的行为改变,python,ctypes,dynamic-linking,Python,Ctypes,Dynamic Linking,我正在为我的博士学位写一个程序来处理来自高速摄像机的数据。项目这款相机在Linux上带有一个.so文件格式的SDK,用于与相机通信和获取图像。如前所述,这是一款高速摄像机,提供大量数据(每分钟几GB)。为了处理这一数量的数据,SDK有一个非常方便的spool函数,该函数通过DMA将数据以FITS文件的形式直接假脱机到硬盘驱动器,FITS文件是一种原始二进制格式,具有天文学中使用的标头。 当我编写一个小的C程序,链接.so文件并以这种方式调用spool函数时,这个函数工作得很好。但是当我用ctyp

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

我将非常感谢任何建议

尽管这款相机是商用的,但有些驱动程序是GPLed的,并且可以使用,尽管有点复杂。(不幸的是,这似乎不是spool函数)我有一个python对象用于Handel相机

该类的开头是:

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
的值不会被截断,而是在Python解释器中以type
int
的形式返回,如果将高位指针作为参数反馈给其他函数而不进行强制转换,则会产生可以预见的有趣结果

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


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

我的猜测是,这不是对假脱机函数本身的调用,而是一个调用序列,它会导致损坏的值被输入库或从库中输出

您是否在64位平台上?不为任何返回64位整数(
long
,带gcc)或指针的内容指定
restype
,将导致这些值被自动截断为32位。此外,
ctypes.c_voidp
处理有点令人惊讶-
ctypes.c_voidp
的值不会被截断,而是在Python解释器中以type
int
的形式返回,如果将高位指针作为参数反馈给其他函数而不进行强制转换,则会产生可以预见的有趣结果

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


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

您确定在
ctypes
代码中正确设置了
argtypes
restype
属性吗?如果您能向我们展示您的代码和相关的C头文件,这可能会有所帮助。该库可能存在缺陷,不会在纯C构建中暴露自己(或在从未测试过的其他编译器/平台上)。听起来像是被一个不透明的共享对象困住了,对于这个对象,您可能只想将一个函数包装在C中并对其进行子处理。您的包装器中也可能存在错误,但我们知道这永远不会发生;)我已经在代码中添加了更多细节,关于子处理它的问题是,驱动器还负责冷却相机等等。所以我必须让它保持加载状态,就我所知,我只能从加载它的进程向它发送命令。我在python代码中使用了多处理模块来分离相机的操作,这个模块能否通过C类型链接代码。您是否为所有要调用的函数设置
argtypes
restype
属性?如果您不这样做,那么ctypes本质上只是根据您提供给它的参数猜测函数期望的类型,它很容易猜错。为了安全起见,我会为您使用的所有函数设置这些属性。我不会为所有调用设置res和arg类型,只为那些提供和接受外来参数(如数组)的调用设置res和arg类型。但是我应该这样做,大多数函数都采用整数,这是ctypes在没有给定argtypes和给定整数时所猜测的。假脱机是一种可以打开和关闭的功能,当我不进行假脱机时,程序可以正常工作,直接在内存中获取数据,所有函数都会给出一个返回码,我会检查它