SWIG C / python和unsigned char指针

时间:2017-09-04 01:26:08

标签: python c++ c swig

我有一个

形式的函数
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的方法(编码,byterray,[0] * 100等)但似乎没有任何工作......

这应该如何运作?

以防万一,这可能会产生一些影响,这是一个C函数,以避免错误我用

包装它
extern "C"
{
...
}

不幸的是我无法更改c代码

4 个答案:

答案 0 :(得分:0)

请尝试使用{{1}}。

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

在手册中可能很容易找到,但这里有

xxxx.h

#pragma once
extern "C" {
  void f(unsigned char *out, const unsigned long long outlen,
    const unsigned char *in, const unsigned long long inlen);
}

xxxx.cc

#include "xxxx.hh"

void f(unsigned char *out, const unsigned long long outlen,
       const unsigned char *in, const unsigned long long inlen) {
  // Really stupid - only writing a fixed output
  out[outlen-1] = (unsigned char) 57;
}

使用

进行编译
g++ -shared -fPIC -Wl,-soname,libxxxx.so -o libxxxx.so xxxx.o

在Python中,使用如下

import ctypes

input = [0,1,2,3]
output = [0,0,0,0]
input = (ctypes.c_uint8 * 4)(*input)
output = (ctypes.c_uint8 * 4)(*output)

h = ctypes.cdll.LoadLibrary('./libxxxx.so')
h.f(output,4,input,4)

# Note how output[3] is 57 or chr(output[3]) is '9'

有关如何将字符串转换为字符数组Converting python string object to c char* using ctypes

的信息,请参阅此文章

答案 3 :(得分:0)

感谢您的回答。

我知道如何使用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的正确性,我在这个答案中避免这样做以保持简单。但应该考虑到这一点。