我正在使用Boost.Python从C++类创建Python模块.我遇到了引用的问题.
Condider以下情况我有一个类Foo,带有重载的get方法,可以通过值或引用返回.
一旦我输入了签名,指定应该使用值返回很容易.但我认为应该可以通过使用a返回引用 return_value_policy.但是,使用看似合适的东西(doc); return_value_policy<reference_existing_object>似乎没有用.
我误解了它的作用吗?
struct Foo {
Foo(float x) { _x = x; }
float& get() { return _x; }
float get() const { return _x; }
private:
float _x;
};
// Wrapper code
BOOST_PYTHON_MODULE(my_module)
{
using namespace boost::python;
typedef float (Foo::*get_by_value)() const;
typedef float& (Foo::*get_by_ref)();
class_<Foo>("Foo", init<float>())
.def("get", get_by_value(&Foo::get))
.def("get_ref", get_by_ref(&Foo::get),
return_value_policy<reference_existing_object>())//Doesn't work
;
}
Run Code Online (Sandbox Code Playgroud)
注意:我知道在没有生命周期管理的情况下引用现有对象可能会很危险.
更新:
看起来它适用于对象但不适用于基本数据类型.
拿这个修改过的例子:
struct Foo {
Foo(float x) { _x = x; }
float& get() { return …Run Code Online (Sandbox Code Playgroud) 我有第三方C++库,其中一些类方法使用原始字节缓冲区.我不太确定如何处理Boost :: Python.
C++库头类似于:
class CSomeClass
{
public:
int load( unsigned char *& pInBufferData, int & iInBufferSize );
int save( unsigned char *& pOutBufferData, int & iOutBufferSize );
}
Run Code Online (Sandbox Code Playgroud)
坚持使用Boost :: Python代码......
class_<CSomeClass>("CSomeClass", init<>())
.def("load", &CSomeClass::load, (args(/* what do I put here??? */)))
.def("save", &CSomeClass::save, (args(/* what do I put here??? */)))
Run Code Online (Sandbox Code Playgroud)
如何将这些原始缓冲区包装在Python中作为原始字符串公开?
我想使用Boost.Python将以下C++函数公开给Python:
int* test1() {
return new int(42);
}
// Now exposing the function with Boost.Python
BOOST_PYTHON_MODULE(libtest1)
{
using namespace boost::python;
def("test1", test1);
}
Run Code Online (Sandbox Code Playgroud)
当我尝试编译这个库时,由于(我的猜测)Boost.Python不知道如何将int*转换为PyObject而发生错误.
我认为需要做的是定义转换结构,如下所示:
template<class T>
struct int_ptr_to_python
{
static PyObject* convert(int* i_ptr)
{
return i_ptr;
}
};
Run Code Online (Sandbox Code Playgroud)
并将其传递给BOOST_PYTHON_MODULE声明:
BOOST_PYTHON_MODULE(libtest1)
{
using namespace boost::python;
def("test1", test1);
to_python_converter<int*, int_ptr_to_python<int*> >();
}
Run Code Online (Sandbox Code Playgroud)
但它也行不通.而且我找不到有关如何处理返回指针的函数的任何信息.
有人可以帮忙吗?
您可以使用getter和setter将属性添加到类中(在简单的情况下):
class<X>("X")
.add_property("foo", &X::get_foo, &X::set_foo);
Run Code Online (Sandbox Code Playgroud)
那么你可以像这样在python中使用它:
>>> x = mymodule.X()
>>> x.foo = 'aaa'
>>> x.foo
'aaa'
Run Code Online (Sandbox Code Playgroud)
但是如何将属性添加到模块本身(而不是类)?
有
scope().attr("globalAttr") = ??? something ???
Run Code Online (Sandbox Code Playgroud)
和
def("globalAttr", ??? something ???);
Run Code Online (Sandbox Code Playgroud)
我可以使用上面两种方式添加我的类的全局函数和对象,但似乎无法像在类中一样添加属性.
我正在使用boost-python为名为的C++类创建python绑定CppClass.必要时,我可以通过预处理参数的小包装函数(例如从python args中提取C++类型)将调用路由到"普通"成员函数,如下所示:
class CppClass
{
public:
CppClass(SpecialParameters p);
void doSomething(int x, float y);
};
using namespace boost::python; // For extract, tuple, init, class_, etc.
class WrapperFuncs
{
public:
static void doSomething(CppClass & c, tuple t)
{
// Special extraction: Convert python arg ( a tuple) into C++ args.
int x = extract<int>(t.attr("__getitem__")(0));
float y = extract<float>(t.attr("__getitem__")(1));
c.doSomething(x,y);
}
};
class_<CppClass, boost::shared_ptr<CppClass> >
("CppClass", init<SpecialParameters>())
.def("doSomething", &WrapperFuncs::doSomething, (arg("t")))
Run Code Online (Sandbox Code Playgroud)
但是我如何为CppClass 构造函数做同样的事情呢?
假设我想获得一些全局/内部c ++对象的引用,一种方法是声明函数boost::python::return_value_policy<reference_existing_object>().
两者GetGlobalObjectA并GetGlobalObjectB返回对原始c ++对象的引用,而不创建新副本;
但是如何GetGlobalObjectByID返回对现有c ++对象的引用?
struct A { uint32_t value; };
struct B { uint64_t value; };
A globalA;
B globalB;
boost::python::object GetGlobalObjectByID(int id)
{
// boost::python::object will return a new copy of C++ object, not the global one.
if (id == 1)
return boost::python::object(&globalA);
else if (id == 2)
return boost::python::object(&globalB);
else
return boost::python::object(nullptr);
}
A& GetGlobalObjectA() { return globalA; }
B& GetGlobalObjectB() { return globalB; }
BOOST_PYTHON_MODULE(myModule)
{
using … 我试图使用boost.python将一段C++代码包装到python lib中,但是,我发现多个实例不能同时运行:
代码(C++):
class Foo{
public:
Foo(){}
void run(){
int seconds = 2;
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
};
BOOST_PYTHON_MODULE(run_test)
{
using namespace boost::python;
class_<Foo>("test", init<>())
.def("run", &Foo::run)
;
}
Run Code Online (Sandbox Code Playgroud)
这是使用CMake(CMake)编译的:
add_library(run_test SHARED run_test.cpp)
target_link_libraries(run_test boost_python python2.7)
Run Code Online (Sandbox Code Playgroud)
并使用以下代码(Python)进行测试:
class Dos(threading.Thread):
def run(self):
printl('performing DoS attack')
proc = test()
proc.run()
for i in range(5):
t = Dos()
t.start()
Run Code Online (Sandbox Code Playgroud)
输出表明代码以非常奇怪的方式并行化.每个线程应该只需要2秒钟,并且我的四核机器上应该同时运行4个线程:
[2011-11-04 13:57:01] performing DoS attack
[2011-11-04 13:57:01] performing DoS attack …Run Code Online (Sandbox Code Playgroud) 我有几个模块为一些简单类型定义转换器(例如int的列表std::vector<int>); 它们是独立模块的一部分,但有时它们都用在一个脚本中,这导致了
RuntimeWarning: to-Python converter for std::vector<int, std::allocator<int> > already registered; second conversion method ignored.
Run Code Online (Sandbox Code Playgroud)
如何检查某种类型的转换器是否已定义并跳过第二次注册?
我有一个在C++中的shared_ptr中保存的对象.该对象是通过python中的python绑定访问的,并传递给另一个试图保持它的绑定C++函数.看来,当对象从C++转到Python时,它会从shared_ptr转换为python对象.然后,当它返回到C++时,它将从python对象转换为新的shared_ptr,但是这个shared_ptr与初始持有shared_ptr无关.
是否可以设置boost-python绑定,以便从python对象到shared_ptr的转换引用原始的shared_ptr内部?
下面是我用来显示问题的删节代码.
在此示例中,对象最初保存在名为s_inital的shared_ptr中.它是通过getSharedPtr函数从python中获取的,然后通过putSharedPtr函数推回到C++中.在putSharedPtr里面,它被复制到weak_ptr s_copied中.检查调试器中的指针显示putSharedPtr中使用的shared_ptr与s_initial没有相同的引用计数内部.最后的断言将触发,因为弱指针s_copied仅与单个强指针(putSharedPtr中使用的指针)相关,并且一旦putSharedPtr完成,该指针就被破坏了.
static shared_ptr<Captured> s_initial;
static weak_ptr<Captured> s_copied;
class UseSharedPtr
{
public:
shared_ptr<Captured> getSharedPtr()
{
return s_initial;
}
void putSharedPtr(shared_ptr<Captured> ptr)
{
s_copied = ptr;
}
};
BOOST_PYTHON_MODULE(test)
{
class_<Captured, shared_ptr<Captured>, boost::noncopyable>("Captured", no_init);
class_<UseSharedPtr, boost::noncopyable>("UseSharedPtr", init<>())
.def("getSharedPtr", &UseSharedPtr::getSharedPtr)
.def("putSharedPtr", &UseSharedPtr::putSharedPtr)
;
}
s_initial = make_shared<Captured>();
const char* chunk = "\
from test import UseSharedPtr \n\
x = UseSharedPtr() \n\
ptr = x.getSharedPtr() \n\
x.putSharedPtr(ptr)\n\
del x \n\
del ptr \n\
";
object result = exec(chunk, mainNamespace, mainNamespace); …Run Code Online (Sandbox Code Playgroud) 我正在尝试构建我的第一个Boost.Python示例.
#include <iostream>
#include <boost/python.hpp>
using namespace boost::python;
class Hello {
public:
std::string greet() {
std::cout << "Hello World" << std::endl;
}
};
BOOST_PYTHON_MODULE(hello)
{
class_<Hello>("Hello")
.def("greet", &Hello::greet);
}
int main() {
std::cout << "Boost.Python Test" << std::endl;
Hello hello;
hello.greet();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:缺少Python开发标题,正如@cdhowie所指出的那样.我找到并包含了所需的头文件.现在链接器抱怨:
10:43:58 **** Build of configuration BoostPythonTest-DPar for project BoostPythonTest
****
make all
Building file: ../src/BoostPythonTest.cpp
Invoking: GCC C++ Compiler
/usr/local/bin/g++-4.7 -I/usr/local/Cellar/python3/3.3.0/Frameworks/Python.framework/Versions/3.3/include/python3.3m -I/usr/include -I/usr/local/Cellar/gcc/4.7.2/gcc/include/c++/4.7.2 -O0 -g3 -p -pg -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/BoostPythonTest.d" -MT"src/BoostPythonTest.d" …Run Code Online (Sandbox Code Playgroud)