Python如何通过SWIG从C ++中获取二进制数据(char *)?

时间:2011-11-17 08:16:34

标签: c++ python char swig

我正在使用SWIG的Python中的C ++函数,现在我遇到了一个问题。 当我将char *从C ++传递给Python时,char *被Python中断。

例如:

example.h文件:

char * fun()
{
    return "abc\0de";
}

现在用Python,我们打电话     example.fun() 它只打印     “ABC” 代替     “ABC \ 0de” “0”后面的数据被Python删除。

我想从C ++中的fun()获取所有字符(它是一个可以包含'\ 0'的二进制数据), 任何建议表示赞赏

3 个答案:

答案 0 :(得分:8)

首先,如果您正在处理二进制数据,则不应使用char *(swig认为它们是普通字符串)。相反,您应该使用void *。 swig提供了一个名为'cdata.i'的模块 - 你应该在接口定义文件中包含它。

包含此功能后,它会提供两个功能 - cdata()memmove()

  • 给定void *和二进制数据的长度,cdata()将其转换为目标语言的字符串类型。
  • memmove()反过来 - 给定一个字符串类型,它会将字符串的内容(包括嵌入的空字节)复制到C void*类型中。

使用此模块处理二进制数据变得更加简单。我希望这就是你所需要的。

example.i
%module example
%include "cdata.i"
%{
void *fun()
{
        return "abc\0de";
}
%}

test.py
import example
print example.cdata(example.fun(), 6)

答案 1 :(得分:6)

C / C ++字符串以NULL结尾,这意味着第一个\0字符表示字符串的结尾。

当一个函数返回一个指向这样一个字符串的指针时,调用者(在本例中为SWIG)无法知道在第一个\0之后是否有更多数据,这就是为什么你只得到第一部分。

首先要做的是改变你的C函数,不仅要返回字符串,还要返回它的长度。由于只能有一个返回值,我们将使用指针参数。

void fun(char** s, int *sz)
{
    *s = "abc\0de";
    *sz = 6;
}

SWIG文档建议使用cstring.i library来包装这些函数。特别是,最后一个宏完全符合您的需要。

%cstring_output_allocate_size(parm, szparm, release)

阅读the docs以了解如何使用它。

答案 2 :(得分:0)

请参阅文档中的8.3 C String Handling

同样来自documentation

  

char *数据类型作为以NULL结尾的ASCII字符串处理。痛饮   将其映射为目标脚本中的8位字符串   语言。 SWIG将目标语言中的字符串转换为   在将字符串传递给C / C ++之前,NULL终止了字符串。默认   处理这些字符串不允许它们嵌入NULL   字节。因此,char *数据类型通常不适合   传递二进制数据。但是,可以更改此行为   通过定义SWIG类型映射。有关详细信息,请参阅类型图章一章   关于这个。