TLDR:是否可以通过python转换器传递C ++指针类型?
这里我为它声明了我的MyStruct和指针类型PMYSTRUCT,转换器模板类PointerConverter和那个python模块:
#include <boost/python.hpp>
namespace py = boost::python;
template<class T, class Converter>
void from_python_converter()
{
py::converter::registry::push_back(&Converter::convertable, &Converter::construct, py::type_id<T>());
}
template<typename POINTER_TYPE>
class PointerConverter
{
public:
static void* convertable(PyObject *obj_ptr) // Detect: Is Pyhton object converatable?
{
static py::object ctypes_c_void_p = py::import("ctypes").attr("c_void_p");
return PyObject_IsInstance(obj_ptr, ctypes_c_void_p.ptr())? obj_ptr: nullptr;
}
static void construct(PyObject *obj_ptr, py::converter::rvalue_from_python_stage1_data *data) // From Python to POINTER_TYPE converter
{
auto storage = reinterpret_cast<py::converter::rvalue_from_python_storage<POINTER_TYPE>*>(data)->storage.bytes;
new(storage) POINTER_TYPE(reinterpret_cast<POINTER_TYPE>(uintptr_t(py::extract<uintptr_t>(py::object(py::handle<>(py::borrowed(obj_ptr))).attr("value")))));
data->convertible = storage;
}
struct MyStruct
{
...
};
typedef MyStruct* PMYSTRUCT;
void foo(PMYSTRUCT p)
{
...
}
BOOST_PYTHON_MODULE(module_name)
{
from_python_converter<PMYSTRUCT, PointerConverter<PMYSTRUCT>>();
py::def("foo", &foo);
}
如您所见,foo()计划通过boost.python转换器机制接收PMYSTRUCT作为参数。但是当我试图通过时:
from module_name import foo
import ctypes
foo(ctypes.c_void_p(100))
我得到例外:
Boost.Python.ArgumentError: Python argument types in
module_name.foo(c_void_p)
did not match C++ signature:
foo(struct MyStruct * __ptr64)
答案 0 :(得分:0)
我自己找到了解决方案。虽然不可能为普通指针实现转换器,但我决定制作一个包装器:
Pointer.h:
#pragma once
template<typename POINTER_TYPE>
class Pointer
{
public:
Pointer(POINTER_TYPE p = nullptr): value(p)
{
}
operator POINTER_TYPE() const
{
return value;
}
template<typename T>
T get() const
{
return reinterpret_cast<T>(value);
}
class Converter
{
public:
Converter()
{
py::to_python_converter<Pointer, Converter>();
py::converter::registry::push_back(&Converter::convertable, &Converter::construct, py::type_id<Pointer>());
if (ctypes_c_void_p.is_none())
{
ctypes_c_void_p = py::import("ctypes").attr("c_void_p");
}
}
static void* convertable(PyObject *obj_ptr)
{
return PyObject_IsInstance(obj_ptr, ctypes_c_void_p.ptr())? obj_ptr: nullptr;
}
static void construct(PyObject *obj_ptr, py::converter::rvalue_from_python_stage1_data *data)
{
// From ctypes.c_void_p
auto storage = reinterpret_cast<py::converter::rvalue_from_python_storage<Pointer>*>(data)->storage.bytes;
py::object value_obj = py::object(py::handle<>(py::borrowed(obj_ptr))).attr("value");
new(storage) Pointer(value_obj.is_none()? 0: reinterpret_cast<POINTER_TYPE>(uintptr_t(py::extract<uintptr_t>(value_obj))));
data->convertible = storage;
}
static PyObject* convert(Pointer const &ptr)
{
return py::incref(ctypes_c_void_p(ptr.get<uintptr_t>()).ptr());
}
private:
static py::object ctypes_c_void_p;
};
POINTER_TYPE value;
};
template<typename POINTER_TYPE>
py::object Pointer<POINTER_TYPE>::Converter::ctypes_c_void_p;
Main.h:
#include <boost/python.hpp>
namespace py = boost::python;
#include "Pointer.h"
typedef Pointer<PMYSTRUCT> MyStructPtr;
Foo.cpp中:
#include "Main.h"
MyStructPtr foo(MyStructPtr p)
{
PMYSTRUCT pointer_as_arg = p;
return new MyStruct;
}
Main.cpp的:
#include "Main.h"
BOOST_PYTHON_MODULE(module_name)
{
MyStructPtr::Converter();
py::def("foo", &foo);
}