我有一个C++类,其中一个成员函数需要一个unsigned char*缓冲区和一个unsigned int长度作为参数并对它们进行操作。我已经使用Boost::Python包装了这个类,并希望从Python脚本中向该类传递预先填充的缓冲区。Python端的缓冲区是使用struct.pack创建的。我无法弄清如何使参数类型匹配,并不断收到Boost.Python.ArgumentError错误。
我尝试了多种方法(直接传递'buf',将'buf'作为ctypes.c_char_p传递,创建一个ctypes.ubyte数组并用'buf'的内容填充它再传递),但似乎都不起作用。
我不明白为什么'LP_c_ubyte'和'unsigned char*'不匹配。
编辑
这是一个Github项目,具有现成的代码库。随意使用。我已经添加了@Tanner的修复。https://github.com/dustingooding/boost_python_ucharp_example
include/Example.h
#ifndef EXAMPLECLASS_H_
#define EXAMPLECLASS_H_
#include <cstdio>
class ExampleClass
{
public:
ExampleClass() {}
virtual ~ExampleClass() {}
void printBuffer(unsigned char* buffer, unsigned int length)
{
for (unsigned int i = 0; i < length; ++i)
{
printf("%c", buffer[i]);
}
printf("\n");
}
};
#endif
src/example.cpp
#include "Example.h"
int main(int argc, char** argv)
{
unsigned char buf[4];
buf[0] = 0x41;
buf[1] = 0x42;
buf[2] = 0x43;
buf[3] = 0x44;
ExampleClass e;
e.printBuffer(buf, 4);
return 0;
}
src/Example_py.cpp
#include <boost/python.hpp>
#include "Example.h"
using namespace boost::python;
BOOST_PYTHON_MODULE(example_py)
{
class_<ExampleClass>("ExampleClass")
.def("printBuffer", &ExampleClass::printBuffer)
;
}
scripts/example.py
#!/usr/bin/env python
import example_py
import struct
import ctypes
buf = struct.pack('BBBB', 0x41, 0x42, 0x43, 0x44)
print 'python:'
print buf
e = example_py.ExampleClass()
print 'c++:'
print e.printBuffer(ctypes.cast(ctypes.c_char_p(buf), ctypes.POINTER(ctypes.c_ubyte)), len(buf))
CMakeLists.txt(不完整)
include_directories(
include
${Boost_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS}
)
add_library(example_py
src/Example_py.cpp
)
target_link_libraries(example_py ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
set_target_properties(example_py PROPERTIES PREFIX "")
add_executable(example src/example.cpp)
target_link_libraries(example example_py)
输出
$ ./example
ABCD
$ ./scripts/example.py
python: ABCD
c++:
Traceback (most recent call last):
File "/home/dustingooding/example/scripts/example.py", line 13, in <module>
print 'c++:', e.printBuffer(ctypes.cast(ctypes.c_char_p(buf), ctypes.POINTER(ctypes.c_ubyte)), len(buf))
Boost.Python.ArgumentError: Python argument types in
ExampleClass.printBuffer(ExampleClass, LP_c_ubyte, int)
did not match C++ signature:
printBuffer(ExampleClass {lvalue}, unsigned char*, unsigned int)
我尝试了多种方法(直接传递'buf',将'buf'作为ctypes.c_char_p传递,创建一个ctypes.ubyte数组并用'buf'的内容填充它再传递),但似乎都不起作用。
我不明白为什么'LP_c_ubyte'和'unsigned char*'不匹配。
编辑
这是一个Github项目,具有现成的代码库。随意使用。我已经添加了@Tanner的修复。https://github.com/dustingooding/boost_python_ucharp_example
ctypes
方法对我来说看起来像是一个 XY 问题,因此我选择不在这个答案中详细讨论它。 - Tanner SansburyLP_c_ubyte
不是unsigned char*
,而是ctypes
知道如何在调度通过ctypes
获得的函数时将其转换为unsigned char*
的类型。Boost.Python 不知道如何将LP_c_ubyte
类型转换为unsigned char*
。 - Tanner Sansbury