我已经开始尝试使用boost python并遇到问题.我试图将一个C++类暴露给python,这没有任何问题.但我似乎无法实现__str__类的功能而不会出现我不明白的构建错误.
我正在使用boostpro的boost 1_42 prebuild.我使用cmake和vs2010编译器构建库.
我有一个非常简单的设置.头文件(tutorial.h)如下所示:
#include <iostream>
namespace TestBoostPython{
class TestClass {
private:
double m_x;
public:
TestClass(double x);
double Get_x() const;
void Set_x(double x);
};
std::ostream &operator<<(std::ostream &ostr, const TestClass &ts);
};
Run Code Online (Sandbox Code Playgroud)
和相应的cpp文件看起来像:
#include <boost/python.hpp>
#include "tutorial.h"
using namespace TestBoostPython;
TestClass::TestClass(double x)
{
m_x = x;
}
double TestClass::Get_x() const
{
return m_x;
}
void TestClass::Set_x(double x)
{
m_x = x;
}
std::ostream &operator<<(std::ostream &ostr, const TestClass &ts)
{
ostr << ts.Get_x() << "\n";
return ostr;
} …Run Code Online (Sandbox Code Playgroud) 我试图从C++实现调用Python函数.我认为它可以通过函数指针实现,但似乎不可能.我一直boost.python用来完成这个.
假设在Python中定义了一个函数:
def callback(arg1, arg2):
#do something
return something
Run Code Online (Sandbox Code Playgroud)
现在我需要将此函数传递给C++,以便可以从那里调用它.如何在C++端编写代码boost.python来实现这一目的?
首先:我查看了相关问题,但遗憾的是它们并没有很大帮助.我正在尝试从外部库中包装枚举和类.
#include <Python.h>
#include <boost/python.hpp>
using namespace boost::python;
#include <libvpsc/rectangle.h>
using vpsc::Rectangle;
using vpsc::Dim;
BOOST_PYTHON_MODULE(adaptagrams)
{
enum_<Dim>("dim")
.value("x", vpsc::XDIM)
.value("y", vpsc::YDIM)
.value("unset", vpsc::UNSET)
;
class_<Rectangle>("Rectangle",
init<double, double, double, double, optional<bool> >())
.add_property("centerX", &Rectangle::getCentreX)
.add_property("centerY", &Rectangle::getCentreY)
.add_property("width", &Rectangle::width, &Rectangle::set_width)
.add_property("height", &Rectangle::height, &Rectangle::set_height)
;
}
Run Code Online (Sandbox Code Playgroud)
并编译:
g++ -fPIC -I/usr/include/python2.7 -c adaptagrams.cpp -o adaptagrams.o
g++ -shared -Wl,-soname,adaptagrams.so -o adaptagrams.so adaptagrams.o -lpython2.7 -lboost_python -lvpsc
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试导入.so模块时,出现错误:
ImportError: dynamic module does not define init function (PyInit_adaptagrams)
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
更新:当我重新启动Python并尝试导入时,我得到的第一个错误是:
ImportError: ./adaptagrams.so: undefined symbol: _ZN8topology13computeStressERKSt6vectorIPNS_4EdgeESaIS2_EE
Run Code Online (Sandbox Code Playgroud)
当我再次尝试时,第二个是从上面动态导入(2.7)和段错误(3.2).Boost是针对2.7和3.2进行编译的,我在每种方法上都链接正确的.
更新2: …
我有一个boost.python项目,我使用cmake和make编译.它是python模块的一部分,我希望能够使用distutils安装该模块.我按照这里的说明创建了一个CMakeLists.txt文件,该文件首先编译共享库,然后设置setup.py,以便make install安装python模块.但是,虽然所有python文件都被distutils识别并移动到构建目录,但共享库却没有,我真的不知道为什么.
我的项目目录结构:
我的setup.py.in文件:
from distutils.core import setup
setup(
name='module',
version='${PACKAGE_VERSION}',
packages=['module', 'module.core', 'module.other_py_files'],
package_dir={'': '${CMAKE_CURRENT_SOURCE_DIR}'},
)
Run Code Online (Sandbox Code Playgroud)
我的CMakeLists.txt:
cmake_minimum_required (VERSION 2.6)
project (module)
add_subdirectory(module/core)
find_program(PYTHON "python")
if (PYTHON)
set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
set(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
set(DEPS "${CMAKE_CURRENT_SOURCE_DIR}/pyQCD/__init__.py")
set(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp")
configure_file(${SETUP_PY_IN} ${SETUP_PY})
add_custom_command(OUTPUT ${OUTPUT}
COMMAND ${PYTHON} ${SETUP_PY} build
COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}
DEPENDS ${DEPS})
add_custom_target(target ALL DEPENDS ${OUTPUT})
install(CODE "execute_process(COMMAND ${PYTHON} ${SETUP_PY} install)")
endif()
Run Code Online (Sandbox Code Playgroud)
我认为distutils应该自动添加共享库扩展来构建目录,或者我在某处出错了?(共享库是一个基于C api(boost.python)构建的可导入的python模块,所以它应该可以工作吗?)
所以,我正在尝试创建一个to_python转换器,它允许我从一个公开的函数返回一个boost :: optional,并且如果设置了可选项,则将其视为T,否则视为None.基于我在C++ Sig上发现的帖子,我编写了以下代码.
template<typename T>
struct optional_ : private boost::noncopyable {
struct conversion {
static PyObject* convert(boost::optional<T> const& value) {
if (value) {
return boost::python::to_python_value<T>()(*value);
}
Py_INCREF(Py_None);
return Py_None;
}
};
explicit optional_() {
boost::python::to_python_converter<boost::optional<T>, conversion>();
}
};
Run Code Online (Sandbox Code Playgroud)
据我所知,它适用于转换选项,但是python会抛出以下异常"TypeError:No to_python(by-value)convert for C++ type:std :: string".我知道C++能够将字符串转换为python,因为我的大多数公开函数都返回字符串.为什么boost :: python :: to_python_value不能识别它,我怎样才能利用它拥有的任何转换器?
通过更改为以下内容(基于本文)修复:
template<typename T>
struct optional_ : private boost::noncopyable {
struct conversion {
static PyObject* convert(boost::optional<T> const& value) {
using namespace boost::python;
return incref((value ? object(*value) : …Run Code Online (Sandbox Code Playgroud) 我正在使用Python绑定(使用boost :: python)表示存储在文件中的数据的C++库.我的大多数半技术用户将使用Python与之交互,因此我需要尽可能将其设为Pythonic.但是,我也会让C++程序员使用API,所以我不想在C++方面妥协以适应Python绑定.
图书馆的很大一部分将由容器制成.为了让python用户看起来很直观,我希望它们的行为类似于python列表,即:
# an example compound class
class Foo:
def __init__( self, _val ):
self.val = _val
# add it to a list
foo = Foo(0.0)
vect = []
vect.append(foo)
# change the value of the *original* instance
foo.val = 666.0
# which also changes the instance inside the container
print vect[0].val # outputs 666.0
Run Code Online (Sandbox Code Playgroud)
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/shared_ptr.hpp>
struct Foo {
double val;
Foo(double a) : val(a) {}
bool operator == (const …Run Code Online (Sandbox Code Playgroud) 我使用Python的几个版本我的电脑上:2.6.6,2.7.6和2.7.9.当我用boost-python编译Boost时,我必须让Python在参数中使用.如果我想要兼容性,我是否要为每个Python版本编译Boost?(这是非常巨大的!)或者有没有办法只使用一个Boost版本和几个python版本?
我有一个C++类,其成员函数可以使用少量到大量的参数.让我们命名那些参数,af.所有参数都有默认值.作为我正在研究的python项目的一部分,我想将这个类暴露给python.目前,成员函数看起来像这样:
class myClass {
public:
// Constructors - set a-f to default values.
void SetParameters(std::map<std::string, double> &);
private:
double a, b, c, d, e, f;
}
void myClass::SetParameters(std::map<std::string, double> const& params) {
// Code to iterate over the map, and set any found key/value pairs to their
// corresponding variable. i.e.- "a" --> 2.0, would set myClass::a to 2.0
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,在Python中,我想使用dict来实现这一点:
>>> A = myModule.myClass();
>>> A.SetParameters({'a': 2.2, 'd': 4.3, b: '9.3'})
Run Code Online (Sandbox Code Playgroud)
通过这种方式,用户可以按任何顺序输入值,并输入任意数量的值以进行覆盖.有关如何在boost :: python中实现这一点的任何想法?在我看来,我可以通过将地图输入更改为boost :: python对象,并使用提取函数来实现此目的.但是,这需要我更改我的库的接口(我更喜欢保留std :: map接口,并为python版本提供一些中间/自动转换技术).思考?
我有一个带有枚举的c ++类,我想模仿它boost::python,以便我可以用MyClass.valuepython 编写.boost::python::class_没有enum_方法,我正在寻找解决方法.
我第一次尝试使用lambdas
MyClass{
enum{value1,value2};
};
class_<MyClass>("MyClass").add_property("value1",&[](){return value1;}).staticmethod("value1");
Run Code Online (Sandbox Code Playgroud)
这给出了编译器错误(in get_signaturefor add_property).我知道我可以为每个值创建getter方法,但这对我来说似乎很尴尬(打字方式).
使用attr:
auto classObj=class_<MyClass>("MyClass");
classObj.attr("value1")=(int)value1;
classObj.attr("value2")=(int)value2;
Run Code Online (Sandbox Code Playgroud)
但它不能像.def其他方法一样链接返回对实例的引用.
有更优雅的解决方案吗?
我有一系列的C++结构,我试图用boost python包装.当这些结构包含数组时,我遇到了困难.我试图以最小的开销执行此操作,不幸的是我无法对结构本身进行任何修改.所以比如说我有
struct Foo
{
int vals[3];
};
Run Code Online (Sandbox Code Playgroud)
我希望能够在python中访问它,如下所示:
f = Foo()
f.vals[0] = 10
print f.vals[0]
Run Code Online (Sandbox Code Playgroud)
现在我正在使用一系列get/set函数,但这些函数非常不优雅且与访问其他非数组成员不一致.这是我目前的解决方案:
int getVals (Foo f, int index) { return f.vals[index]; }
void setVals (Foo& f, int index, int value) { f.vals[index] = value; }
boost::python::class_< Foo > ( "Foo", init<>() )
.def ( "getVals", &getVals )
.def ( "setVals", &setVals );
Run Code Online (Sandbox Code Playgroud)
我可以使用get/set函数(因为在某些情况下我需要实现自定义get或set操作)但是我不确定如何合并[]运算符来访问数组的元素.在其他可以使用[]运算符访问的类中,我已经能够使用_ getitem _和_ setitem _这些已经完美地运行了,但是我不知道如果可能的话我会如何对类成员执行此操作.
boost-python ×10
c++ ×7
python ×7
boost ×3
callback ×1
cmake ×1
compilation ×1
distutils ×1
enums ×1