SWIG C/python 和无符号字符指针

Posted

技术标签:

【中文标题】SWIG C/python 和无符号字符指针【英文标题】:SWIG C/python and unsigned char pointers 【发布时间】:2017-09-04 01:26:07 【问题描述】:

我在表单中有一个函数

void f(unsigned char *out, const unsigned long long outlen,
       const unsigned char *in, const unsigned long long inlen);

当我尝试使用它时:

data_in = ['a', 'b', 'c', 'd', 'e']
data_out = [0]*100
f(data_out, len(data_out), data_in, len(data_in))

(其实我是想传bytearrays)

我得到类似的东西:

Traceback (most recent call last):
  File "xxxx/basic_test.py", line 6, in <module>
    f(data_out, len(data_out), data_in, len(data_in))
TypeError: in method 'f', argument 1 of type 'unsigned char *'

我尝试了不同的传递 data_out 的方法(编码、字节数组、[0]*100 等)但似乎没有任何效果......

这应该如何工作?

以防万一,这可能会产生一些影响,这是一个 C 函数,所以为了避免损坏,我用

包装它
extern "C"

...

很遗憾,我无法更改 c 代码

【问题讨论】:

尝试使用ctypes,分配一个数组并通过引用传递。 C != C++。请确保使用您使用的实际语言进行标记(大概是 C)。 它是嵌入在 C++ 11 应用程序中的遗留代码。编译器是 C++(修改等),这就是我澄清 extern "C" 的原因,因为它确实改变了函数的签名。 【参考方案1】:

您的 python 字符串似乎与 C 函数的预期参数类型不兼容。 this 可能会对您有所帮助。它建议使用 c_char_p 来获得正确的类型。也就是说,如果您想在不复制字符串的情况下这样做,但有一些限制。

如果您可以根据需要定义或复制字符串,则有 ctypes,其中一个是 c_ubyte

【讨论】:

【参考方案2】:

感谢您的回答。

我知道如何使用 ctypes,但我的问题是关于 SWIG,因为我也计划为其他语言生成包装器。

存在无法修改的遗留代码(类 C),但它是更大的 C++11 库的一部分。这意味着我可能会发现修改问题等。我不想修改我公开的函数的签名。他们是unsigned char* 的原因是因为这是原始数据。不是典型的以零结尾的 char* 字符串。 (您可以通过查看unsigned 获得提示)

我寻求的干净解决方案是,给定一个函数

bool foo(unsigned char* data)

   ...
 

编写一个 C++ 包装器(在某些情况下我使用了基于模板的技巧)

bool bar(vector<unsigned char> &x)

   foo(x.data())

在我做的接口文件中

%include "std_vector.i"
namespace std 
  %template(ucharVector) vector<unsigned char>;

... include library, etc...

和 Python:

data = lib.ucharVector([1, 2, 3, 4])
answer = lib.bar(data)

注意:关于 const 的正确性,我在这个答案中避免这样做以保持简单。但应该考虑到这一点。

【讨论】:

【参考方案3】:

尝试改用unsigned char data[]

如果您使用的是 C++,请尝试通过 STL 中的 String 类传入。

【讨论】:

以上是关于SWIG C/python 和无符号字符指针的主要内容,如果未能解决你的问题,请参考以下文章

c中的有符号字符和无符号字符之间的区别

SWIG:将 Python 字符串传递给 void 指针类型的参数

有符号和无符号字符之间的比较

Arduino 在 uint32_t 和无符号字符之间转换

创建 Java 实用函数以将无符号字符数组转换为字符串

C++ 中的 LPWSTR、wchar_t* 和无符号短指针