Python将字符串对象转换为ctypes(unsigned char*)

2024-04-29 19:44:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我想使用具有以下签名的函数的DLL文件-

bool isValid = isImageValid((unsigned char *) buff, const __uint32& buffLen, 
                            int imageW, int imageH, __uint32 requiredSize);

现在,buff必须是从一个字符串得到的,这个字符串等于

^{pr2}$

由于pyBuff很大(主要是),我不想分配一个新的cuchar数组和副本,而是要利用原来的缓冲区。基本上,获取pyBuff对象的char缓冲区并将其作为ctypes(c\ubyte*)引用。在

我最接近的是:

buff = cast(pyBuff, POINTER(c_ubyte))

但我不确定这是我想要的类型。不管怎样,函数给出了以下错误

WindowsError: exception: access violation writing 0x00000000

我很乐意为您效劳。。在

还有-两个简短的问题:

  1. 下面的定义是正确的吗,假设在这个DLL的现有C包装器中(我将它作为引用使用),调用这个函数的函数有签名:(const char * buff, const __uint32& buffLen)

    byref(c_ulong(len(pyBuff)) 
    
  2. CDLL和WinDLL有什么区别,使用哪个是正确的?在

Tags: 文件函数字符串buffint缓冲区booldll
1条回答
网友
1楼 · 发布于 2024-04-29 19:44:45

如果您只有Python字符串,并且您确信isImageValid不会修改其内容,那么您只需将buff参数声明为类型c_char_p。不会复制缓冲区内容。在

c_char_p_type_代码是'z'。在setter函数_ctypes/cfield.c : z_set的2.5.4源代码中,您可以看到对于str对象,它只使用底层的ob_sval指针:

1309    if (PyString_Check(value)) {
1310        *(char **)ptr = PyString_AS_STRING(value);
1311        Py_INCREF(value);
1312        return value;

其中宏定义如下:

^{pr2}$

也就是说,如果您可以读取源文件,您可能更喜欢将其读入可变缓冲区。下面是如何将内容读入ctypesc_char数组(在2.5.4中测试过):

创建要读取的测试文件:

>>> open('tmp.txt', 'w').write('''\
... This is a test.''')

c_uint32中获取文件大小,创建缓冲区,并读入文件内容:

>>> import os
>>> from ctypes import *
>>> buffLen = c_uint32()
>>> buffLen.value = os.path.getsize('tmp.txt')
>>> buff = (c_char * buffLen.value)()
>>> open('tmp.txt').readinto(buf)
15
>>> buff.value
'This is a test.'

关于您的另外两个问题,我将设置如下函数原型:

lib = CDLL(path_to_dll)
isImageValid = lib.isImageValid
isImageValid.argtypes = c_char_p, POINTER(c_uint32), c_int, c_int, c_uint32
isImageValid.restype = c_bool

给定上述argtypes定义,ctypes将通过引用自动传递buffLen。也可以显式使用byref(buffLen)。在

CDLL用于cdecl(C声明)调用约定,其中调用方清理堆栈。这允许变量函数,如printfWinDLL用于stdcall约定,其中被调用方清理堆栈。stdcall主要由32位win32api使用,例如Kernel32函数。请参阅维基百科关于x86 calling conventions的文章。在

相关问题 更多 >