- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个 C++ 类,它有一个成员函数,它接受一个 unsigned char* 缓冲区和一个 unsigned int 长度作为参数并对它们进行操作。我已经用 Boost::Python 包装了这个类,并希望将一个预填充的缓冲区从 Python 脚本传递给这个类。 Python 端缓冲区是使用 struct.pack 创建的。我不知道如何使参数类型匹配并不断收到 Boost.Python.ArgumentError。
#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
#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;
}
#include <boost/python.hpp>
#include "Example.h"
using namespace boost::python;
BOOST_PYTHON_MODULE(example_py)
{
class_<ExampleClass>("ExampleClass")
.def("printBuffer", &ExampleClass::printBuffer)
;
}
#!/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))
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
最佳答案
可能值得考虑将 Pythonic 辅助函数公开为 ExampleClass.printBuffer
Python 的方法,委托(delegate)给 c-ish ExampleClass::printBuffer
成员函数。例如,这将允许 Python 用户调用:
import example
import struct
buf = struct.pack('BBBB', 0x41, 0x42, 0x43, 0x44)
e.printBuffer(buf)
而不是要求用户执行正确的 ctypes
类型转换和定型。
struct.pack()
方法返回 str
Python2 中的对象和 bytes
Python3 中的对象,因此辅助 C++ 函数需要使用 str
中的元素填充连续的内存块。或 bytes
. boost::python::stl_input_iterator
可以提供一种方便的方式来构造C++容器,例如std::vector<char>
,来自 Python 对象,例如 str
或 bytes
.唯一奇怪的是 stl_input_iterator
期望 Python 类型支持可迭代协议(protocol),即 str
不做。但是,内置 iter()
Python 方法可用于创建可迭代对象。
/// @brief Auxiliary function used to allow a Python iterable object with char
/// elements to be passed to ExampleClass.printBuffer().
void example_class_print_buffer_wrap(
ExampleClass& self,
boost::python::object py_buffer)
{
namespace python = boost::python;
// `str` objects do not implement the iterator protcol (__iter__),
// but do implement the sequence protocol (__getitem__). Use the
// `iter()` builtin to create an iterator for the buffer.
// >>> __builtins__.iter(py_buffer)
python::object locals(python::borrowed(PyEval_GetLocals()));
python::object py_iter = locals["__builtins__"].attr("iter");
python::stl_input_iterator<char> begin(
py_iter(py_buffer)), end;
// Copy the py_buffer into a local buffer with known continguous memory.
std::vector<char> buffer(begin, end);
// Cast and delegate to the printBuffer member function.
self.printBuffer(
reinterpret_cast<unsigned char*>(&buffer[0]),
buffer.size());
}
创建辅助函数后,只需要将其公开为ExampleClass.printBuffer
即可。方法:
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<ExampleClass>("ExampleClass")
.def("printBuffer", &example_class_print_buffer_wrap)
;
}
这是一个完整的例子demonstrating这种方法:
#include <cstdio>
#include <vector>
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
// Mocks...
/// @brief Legacy class that cannot be changed.
class ExampleClass
{
public:
void printBuffer(unsigned char* buffer, unsigned int length)
{
for (unsigned int i = 0; i < length; ++i)
{
printf("%c", buffer[i]);
}
printf("\n");
}
};
/// @brief Auxiliary function used to allow a Python iterable object with char
/// elements to be passed to ExampleClass.printBuffer().
void example_class_print_buffer_wrap(
ExampleClass& self,
boost::python::object py_buffer)
{
namespace python = boost::python;
// `str` objects do not implement the iterator protcol (__iter__),
// but do implement the sequence protocol (__getitem__). Use the
// `iter()` builtin to create an iterator for the buffer.
// >>> __builtins__.iter(py_buffer)
python::object locals(python::borrowed(PyEval_GetLocals()));
python::object py_iter = locals["__builtins__"].attr("iter");
python::stl_input_iterator<char> begin(
py_iter(py_buffer)), end;
// Copy the py_buffer into a local buffer with known continguous memory.
std::vector<char> buffer(begin, end);
// Cast and delegate to the printBuffer member function.
self.printBuffer(
reinterpret_cast<unsigned char*>(&buffer[0]),
buffer.size());
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<ExampleClass>("ExampleClass")
.def("printBuffer", &example_class_print_buffer_wrap)
;
}
交互使用:
>>> import example
>>> import struct
>>> buf = struct.pack('BBBB', 0x41, 0x42, 0x43, 0x44)
>>> print 'python:', buf
python: ABCD
>>> e = example.ExampleClass()
>>> e.printBuffer(buf)
ABCD
关于python - 如何使用 boost.python 将预填充的 "unsigned char*"缓冲区传递给 C++ 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32634765/
这个问题在这里已经有了答案: Why don't Java's +=, -=, *=, /= compound assignment operators require casting? (11 个
当我尝试运行以下代码时,List(.of) 无法编译并给出主题错误。 package collections; import java.util.LinkedHashSet; import java.
我正在尝试编译使用 ChatScript 库的程序。这是我在名为 main.cpp 的文件中的代码: #include #include "common.h" using namespace std
我想在我的程序中外部使用 ChatScript。在documents它说: Embedding Step #1 First, you will need to modify `common.h and
假设我有一个 char,我想用一行代码将其 strcat() 转换为 char 数组。对于 [一个非实用的] 示例: strcat("ljsdflusdfg",getchar()); 或者我想做相反的
我有以下类型签名: *Main Lib> let f :: a -> a -> a -> a; f = undefined *Main Lib> let x :: Char; x = undefin
我正在学习如何在 C 中使用指针(使用 malloc 和 free),但我在这个练习中遇到了一些麻烦。我只想制作一个指针数组,我想在其中保存每个单词的方向。然后我想为一个特定的词做一个 free(),
我有一个字符*: char* version = "10.5.108"; 我想通过字符分隔符获取两个新的 char*。 char delimiter = '.'; 执行以下代码后: printf("|
最近在学习Cpp,今天在学习使用Clion做测试的时候,发生了奇怪的事情。 这是我的代码 int main() { char c = 'b'; char carr[1]{'a'};
我对 c 很陌生,我正在审查一些代码。我遇到了这个: static char * fromDataType; static char * toDataType; static char * fromR
我有一个像这样的动态结构: struct network { int count; char** ips; } 如果我知道每个字符串数组都是 16 个字节(即 INET_ADDRSTR
我有一个旧程序,其中使用了一些库函数,但我没有那个库。 所以我正在使用 C++ 库编写该程序。在那个旧代码中有一些函数是这样调用的 *string = newstrdup("这里有一些字符串"); 字
我正在编写一个函数,该函数接受 ArrayList,然后将每个 char[] 复制到另一个增加长度的 char[] 中,然后将新的 char[] 添加到新的 ArrayList 中。当我尝试复制数组时
我正在寻找 map >并生成每个可能的 map从它。 我知道这可能会占用大量内存并需要一些时间。 每个map需要包含每个字母 a-z,并映射到唯一的 a-z 字符。 IE。啊bjcp迪EVfh嘎血红蛋
#define NAME_LEN 20 #include "stdio.h" #include "stdlib.h" #include "string.h" #pragma warning(disab
所以我必须创建一个函数来找到一对带有第一个字母并返回第二个字母的函数。 我实际上找到了一个答案,但是使用 map 功能却找不到。 lookUp :: Char -> [(Char, Cha
我最近接受采访并要求写mystrcat(*s1, *s2, *s3) 其中s1 和s2 是源字符串连接结果由 s3 给出。有人告诉我,不要担心 s3 的内存分配,并假设 s1 和 s2 不是空/无效字
今天我与一位同事讨论了他(对我来说)不寻常的“main”函数签名。他喜欢这样声明: int main(int argc, char* (*argv)[]) { printf("at index
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: What's the difference between new char[10] and new cha
通常字符串文字是 const char[] 类型。但是当我把它当作其他类型时,我得到了奇怪的结果。 unsigned char *a = "\355\1\23"; 使用此编译器会抛出警告“初始化中的指
我是一名优秀的程序员,十分优秀!