Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-将字符串对象转换为ctypes(无符号字符*)_Python_Ctypes - Fatal编程技术网

Python-将字符串对象转换为ctypes(无符号字符*)

Python-将字符串对象转换为ctypes(无符号字符*),python,ctypes,Python,Ctypes,我想使用具有以下签名的函数的DLL文件- bool isValid = isImageValid((unsigned char *) buff, const __uint32& buffLen, int imageW, int imageH, __uint32 requiredSize); 现在,buff必须由一个字符串生成,我将得到一个与python包装器等价的字符串 pyBuff = open(someimagefile,

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

bool isValid = isImageValid((unsigned char *) buff, const __uint32& buffLen, 
                            int imageW, int imageH, __uint32 requiredSize);
现在,buff必须由一个字符串生成,我将得到一个与python包装器等价的字符串

pyBuff = open(someimagefile, 'rb').read()
由于pyBuff很大(大部分情况下),我不想分配新的uchar数组和副本,而是想利用原始缓冲区。基本上,获取pyBuff对象的char缓冲区,并将其引用为ctypes(c_ubyte*)

我最接近它的是:

buff = cast(pyBuff, POINTER(c_ubyte))
但我不确定这是我想要的类型。无论如何,函数给了我以下错误

WindowsError: exception: access violation writing 0x00000000
我很高兴能得到任何帮助

还有两个简短的问题:

  • 以下定义是否正确,因为在这个DLL的现有C包装(我正在使用它作为参考)中,调用(也)这个DLL的函数具有签名:
    (const char*buff,const\uuint32&buffLen)

  • CDLL和Windl之间有什么区别,哪一个是正确的

  • 如果您只有Python字符串,并且您确信
    isImageValid
    不会修改其内容,那么您可以将
    buff
    参数声明为type
    c\u char\p
    。缓冲区内容将不会被复制

    c\u字符p
    \u类型
    代码为“z”。在setter函数的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;
    
    其中宏的定义如下:

    #define PyString_AS_STRING(op) (((PyStringObject *)(op))->ob_sval)
    
    也就是说,如果您可以读取源文件,您可能更愿意将其读入可变缓冲区。以下是如何将内容读入ctypes
    c_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
    
    ctypes将根据上述
    argtypes
    定义,通过引用自动传递
    buffLen
    。您还可以显式使用
    byref(buffLen)


    CDLL
    用于cdecl(C声明)调用约定,在该约定中,调用方清理堆栈。这允许可变功能,如
    printf
    windl
    用于stdcall约定,在该约定中,被调用方清理堆栈。stdcall主要由32位Win32 API使用,如Kernel32函数。请参阅维基百科上的文章。

    这是Python 2还是3?2.5。我必须经常使用这个版本。我可能不清楚这一点,但我无法访问文件本身,只能在读取字符串对象后访问它。我必须创建C数组并进行复制,还是可以使用已经分配给Py字符串的缓冲区?对于其他的一切,非常感谢。@UriElias:我修改了我的答案,补充了关于
    c\u char\p
    如何工作的信息。我希望有帮助。
    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