Python ctypes:传递一个字符串数组

时间:2016-12-06 18:14:02

标签: python c arrays string ctypes

我在Python 2.7中有一个字符串数组,我希望通过ctypes传递给C函数:

unsigned int SetParams(unsigned int count, const char **params)

所以我可以在python中定义参数:

import ctypes as ct
lib = ct.cdll.LoadLibrary('...')
lib.SetParams.restype  = ct.c_uint
lib.SetParams.argtypes = [ct.c_uint, ct.POINTER(ct.c_char_p)]

但是现在当我在Python函数中给出一组参数时,我想在上面的库调用中使用它,我该如何实际调用它?我在想这样的事情:

def setParameters(strParamList):
    numParams    = len(strParamList)
    strArrayType = ct.c_char_p * numParams
    strArray     = strArrayType()
    for i, param in enumerate(strParamList):
        strArray[i] = param
    lib.SetParams(numParams, strArray)

我刚开始使用ctypes并想知道是否有更自动化的方法来执行此操作?赋值strArray[i] = param实际上是否正在重新分配?如果是这样,这看起来相当昂贵 - 是否有办法将字符串指针指向Python分配的缓冲区,或者它们不是以NULL结尾?

更新我确实查看了几个相关的问题,但找不到直接处理相同问题的问题。非常感谢你

2 个答案:

答案 0 :(得分:1)

你认为正确。该代码有效。请致电,例如:

setParameters(['abc','def','ghi'])

我没有查看源代码,但是Python 2.7(32位)上的ctypes确实传递了内部Python缓冲区(通过修改C函数中传递的字符串并在之后打印它来测试在Python中调用),这就是为什么你应该只将Python字符串传递给带const char*或至少知道不修改字符串的函数。由于Python字符串是不可变的,因此在C下写入它们是禁止的。使用ctypes.create_string_buffer创建一个可写字符串以传递给非const char*

答案 1 :(得分:0)

我需要对 forpython 函数中的 setParameters 循环进行以下调整

for i, param in enumerate(strParamList):
   if isinstance(param, bytes):
      strArray[i] = c_char_p(param)
   else:
      strArray[i] = c_char_p(param.encode('utf-8'))

如果 setParameters 的数组参数是 [b'abc', b'def']['abc','def'],这会起作用。