我正在努力从Python str转换为C ++,然后再转换回来。为了与Python 2/3兼容,我认为分别为Py2 / 3使用str / bytes就足够了(定义)。
请注意,这是从较大的代码库中提取的;对于任何丢失的进口商品表示歉意。
// C++ stuff compiled to convertor.so
#include "Python.h"
#if PY_MAJOR_VERSION >= 3
#define PyString_Size PyBytes_Size
#define PyString_AsString PyBytes_AsString
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#endif
template<typename T>
struct vec {
T *ptr;
i64 size;
};
extern "C"
vec<uint8_t> str_to_char_arr(PyObject* in) {
int64_t dimension = (int64_t) PyString_Size(in);
vec<uint8_t> t;
t.size = dimension;
t.ptr = (uint8_t*) PyString_AsString(in);
return t;
}
extern "C"
PyObject* char_arr_to_str(vec<uint8_t> inp) {
Py_Initialize();
PyObject* buffer = PyString_FromStringAndSize((const char*) inp.ptr, inp.size);
return buffer;
}
# Python stuff
class Vec(Structure):
_fields_ = [
("ptr", POINTER(c_wchar_p)),
("size", c_long),
]
lib = to_shared_lib('convertor')
lib_file = pkg_resources.resource_filename(__name__, lib)
utils = ctypes.PyDLL(lib_file)
str_to_char_arr = utils.str_to_char_arr
str_to_char_arr.restype = Vec()
str_to_char_arr.argtypes = [py_object]
encoded = str_to_char_arr('abc'.encode('utf-8'))
char_arr_to_str = utils.char_arr_to_str
char_arr_to_str.restype = py_object
char_arr_to_str.argtypes = [py_object.ctype_class]
result = ctypes.cast(encoded, ctypes.POINTER(Vec())).contents
decoded = char_arr_to_str(result).decode('utf-8')
在python 3.5上使用'abc'
进行尝试似乎会产生'\x03\x00\x00'
,这显然意味着出了点问题。
有人可以发现问题吗?
答案 0 :(得分:0)
可能是您希望使用UCS2,并且为UCS4配置了Python。另请参见Building an UCS4 string buffer in python 2.7 ctypes
答案 1 :(得分:0)
尚未设法使此功能适用于Python 2;也许有人更了解Python版本之间的unicode / str / bytes差异来解决此问题。同样,这意味着我遇到的问题可能与另一个软件包有关,不幸的是我无法控制atm。
不过,这是一些适用于Python 3.5和clang 6.0的工作代码(对我来说)。
#include "Python.h"
#if PY_MAJOR_VERSION >= 3
#define PyString_Size PyBytes_Size
#define PyString_AsString PyBytes_AsString
#define PyString_FromStringAndSize PyBytes_FromStringAndSize
#endif
template<typename T>
struct vec {
T *ptr;
int64_t size;
};
extern "C"
vec<uint8_t> str_to_char_arr(PyObject* in) {
int64_t dimension = (int64_t) PyString_Size(in);
vec<uint8_t> t;
t.size = dimension;
t.ptr = (uint8_t*) PyString_AsString(in);
return t;
}
extern "C"
PyObject* char_arr_to_str(vec<uint8_t> inp) {
Py_Initialize();
PyObject* buffer = PyString_FromStringAndSize((const char*) inp.ptr, inp.size);
return buffer;
}
# Python
from ctypes import *
import pkg_resources
class Vec(Structure):
_fields_ = [
("ptr", POINTER(c_char_p)),
("size", c_long),
]
lib = 'test.so'
lib_file = pkg_resources.resource_filename(__name__, lib)
utils = PyDLL(lib_file)
str_to_char_arr = utils.str_to_char_arr
str_to_char_arr.restype = Vec
str_to_char_arr.argtypes = [py_object]
encoded = str_to_char_arr('Bürgermeister'.encode('utf-8'))
char_arr_to_str = utils.char_arr_to_str
char_arr_to_str.restype = py_object
char_arr_to_str.argtypes = [Vec]
decoded = char_arr_to_str(encoded).decode('utf-8')
print(decoded) # Bürgermeister
将c_char_p
更改为c_wchar_p
似乎没有效果(?)。仍然有效。