我有一个目前用Python编写的系统,可以分为后端和前端层.Python太慢了,所以我想用快速编译的语言重写后端,同时在Python中保留前端,以便从Python调用后端功能.这样做的最佳选择是什么?
我考虑过cython,但写作非常有限且繁琐,并没有那么快.从我记得的Boost Python for C++开始,维护语言之间的桥梁非常烦人.有更好的选择吗?
我的主要因素是:
我main.cpp喜欢这样:
#include <boost/python.hpp>
const char* greeting()
{
return "Hello world?";
}
BOOST_PYTHON_MODULE(test)
{
using namespace boost::python;
def("greeting", greeting);
}
Run Code Online (Sandbox Code Playgroud)
和一个CMakeLists.txt文件:
project(test)
cmake_minimum_required(VERSION 2.8)
# get boost
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost COMPONENTS
system
thread
python
REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
# get python
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
link_directories(${PYTHON_LIBRARIES})
add_library(test SHARED
main.cpp
)
Run Code Online (Sandbox Code Playgroud)
我可以跑cmake,make也很好.它libtest.so为我输出一个漂亮的小文件.为了测试它,我有一个像这样的Python脚本:
import libtest
print(libtest.greeting())
Run Code Online (Sandbox Code Playgroud)
在同一目录中运行它libtest.so会产生以下错误:
Traceback (most recent call last):
File "test.py", line 1, in <module>
import libtest
ImportError: …Run Code Online (Sandbox Code Playgroud) 我最近开始使用Boost的Python库来包装一个相当大的C++库的一部分.
很偶然,我发现Boost Python创建的每个Python对象至少比Python List的大小要大.
使用noddy_NoddyType例如从C-Python的API文档,我可以很容易地露出新对象类型实例,noddy_NoddyObject.
使用原始C-Python API,这与自定义Python对象一样小而简单: -
>>> import noddy, sys
>>> print sys.getsizeof( noddy.Noddy ) # PyTypeObject size?
872
>>> print sys.getsizeof( noddy.Noddy() ) # PyObject size
16
Run Code Online (Sandbox Code Playgroud)
并与基础对象进行比较: -
>>> print sys.getsizeof( object )
872
>>> print sys.getsizeof( object() )
16
Run Code Online (Sandbox Code Playgroud)
这是预期的,但是当我noddy_NoddyObject使用Boost Python 公开时呢?
>>> print sys.getsizeof( noddy.Noddy )
904
>>> print sys.getsizeof( noddy.Noddy() )
80
Run Code Online (Sandbox Code Playgroud)
说什么?!!那不太理想......对象实例比它们需要的大5倍!
(这在非64位计算机上会有所不同.)
我想使用Boost :: Python绑定operator(),但我真的不知道如何做到这一点.考虑这个例子:
C++:
class Queuer
{
public:
void Queuer::operator()(const qfc::Queue & iq, const qfc::Message & im) const;
void Queuer::operator()(const qfc::Agent & ia, const qfc::Message & im) const;
// some other overloaded operator() methods
};
Run Code Online (Sandbox Code Playgroud)
所以在Python脚本中,导入我正在使用的模块(称为qfc)后,我想这样做:
蟒蛇:
>>> queuer = qfc.Queuer()
// instantiating a Message an Agent and a Queue object
>>> queuer(queue,message)
>>> queuer(agent,message)
>>> ...
Run Code Online (Sandbox Code Playgroud)
你对这个怎么办了吗?也许用boost :: python调用<>?
谢谢你,凯文
我升级到Mavericks,经过大量故障排除后现在无法构建我的应用程序。
链接期间,我收到错误消息
Undefined symbols for architecture x86_64:
"boost::python::objects::function_object(boost::python::objects::py_function const&, std::pair<boost::python::detail::keyword const*, boost::python::detail::keyword const*> const&)
.
.
.
"boost::python::objects::register_dynamic_id_aux(boost::python::type_info, std::pair<void*, boost::python::type_info> (*)(void*))"
Run Code Online (Sandbox Code Playgroud)
我正在使用Macports中的g ++,特别是g ++-mp-4.4。Clang不是我的项目的选项,因为我的项目依赖于OpenMP,而OpenMP当前与Clang不兼容。
我没有使用过C ++ 11运行时,但是macports中的Boost.Python库(我在链接过程中使用的库)与此链接。
otool -L libboost_python-mt.dylib
libboost_python-mt.dylib:
/opt/local/lib/libboost_python-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
Run Code Online (Sandbox Code Playgroud)
这是我问题的根源吗?使用Clang编译项目的一部分成功(并克服了此链接错误阶段),但是正如我提到的,我需要OpenMP。
值得注意的是,运行:
nm libboost_python-mt.dylib | c++filt | grep boost::python::objects::function_object
Run Code Online (Sandbox Code Playgroud)
输出
0000000000013d60 T boost::python::objects::function_object(boost::python::objects::py_function const&)
0000000000013d00 T boost::python::objects::function_object(boost::python::objects::py_function const&, std::__1::pair<boost::python::detail::keyword const*, boost::python::detail::keyword …Run Code Online (Sandbox Code Playgroud) 使用Boost :: Python,有没有办法让Python 3.2作为bytes对象可以访问原始C++缓冲区?
对于一个非常相似的问题,有一个Python 2答案,但PyBuffer_FromReadWriteMemoryPython 3中描述的函数不再存在.
编辑:感谢user2167433的回答,我真正想要的是一个只读的memoryview对象,而不是一个bytes对象(使用memoryview避免复制我相信的缓冲区).
我在CPP中使用ITK编写了一个类,它读取目录中的所有文件然后对它们进行平均.我想在使用Python构建的管道中使用此类.
我之前曾尝试使用Swig来包装模板代码,但根据swig文档,它没有模板支持,并且需要明确指定类型名称.但是当我在Python中使用ITK时,界面与我对Swig生成的模板代码的期望非常不同(类型名称根本没有在函数/类名中指定,这与Swig文档所说的相反).
我的代码中的一个小片段说明了该类的用法如下所示:
typedef unsigned char PixelType;
typedef itk::Image<PixelType, 2> ImageType;
typedef itk::NaryMeanImageFilter< ImageType, ImageType > FilterType; // custom class
typedef itk::ImageFileReader<ImageType> ReaderType;
typedef itk::ImageFileWriter<ImageType> WriterType;
ImageType::Pointer image = ImageType::New();
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
FilterType::Pointer filter = FilterType::New(); // custom class
for (unsigned int i = 0; i< fileNames.size(); ++i)
{
reader->SetFileName(fileNames[i]);
filter->SetInput(i, reader->GetOutput()); // custom class
}
writer->SetFileName(outName);
writer->SetInput(filter->GetOutput());
writer->Update();
Run Code Online (Sandbox Code Playgroud)
可以在Git存储库中看到该类的代码.我没有使用Boost :: Python增加项目依赖性的问题,但我需要一个起点继续.任何帮助将非常感激.
谢谢.
更新:
Python中的预期用法是,
readerType=itk.ImageFileReader[inputImageType] …Run Code Online (Sandbox Code Playgroud) 假设我有以下两个C ++类(无法修改):
struct A
{
// stuff
};
struct B
{
// B will internally hold a reference to a
B(A& a, some_cpp_only_type arg);
};
Run Code Online (Sandbox Code Playgroud)
我正在尝试包装B类,并some_cpp_only_type从Python接口隐藏该参数(B没有此参数,没有替代构造函数)。
我现在有以下包装器代码:
using namespace boost::python;
boost::shared_ptr<B> make_B(A& a)
{
return boost::make_shared<B>(a, get_cpp_only_instance());
}
BOOST_PYTHON_MODULE(my_module)
{
class_<B, boost::noncopyable>("B", no_init)
.def("__init__", make_constructor(&make_B));
}
Run Code Online (Sandbox Code Playgroud)
现在这行得通,因为我在APython内部持有对包装对象的引用。但是,我真的很想至少在B销毁该实例之前保持这种状态。我尝试将with_custodian_and_ward_postcall呼叫策略添加到中make_constructor,但出现了几页无意义的编译器错误(甚至来自Clang)。这是修改后的无效代码:
using namespace boost::python;
boost::shared_ptr<B> make_B(A& a)
{
return boost::make_shared<B>(a, get_cpp_only_instance());
}
BOOST_PYTHON_MODULE(my_module)
{
class_<B, boost::noncopyable>("B", no_init)
.def("__init__", make_constructor(&make_B, with_custodian_and_ward_postcall<0,1>()));
}
Run Code Online (Sandbox Code Playgroud)
使用时如何正确指定通话政策 …
请注意,我被限制使用Python 2.6.我有一个Python 2.6应用程序,它使用一个用boost-python构建的C++多线程API库.我的用例只是从C++ boost线程执行Python函数回调,但尽管有许多不同的尝试和研究所有可用的在线资源,我还没有找到任何有效的方法.所有提出的解决方案围绕的功能的不同组合:Py_Initialize*,PyEval_InitThreads,PyGILState_Ensure,PyGILState_Release但在尝试所有可能的组合后一无所获工程实践中如
因此,这个问题:如何从C++启动和运行Python线程?我基本上想要:创建它,用Python目标函数对象运行它并忘记它.
那可能吗?
我正在尝试从我的MacOS High Sierra上的此链接构建此简单的boost python演示。
以下是hello_ext.cpp:
#include <boost/python.hpp>
char const* greet()
{
return "hello, world";
}
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
Run Code Online (Sandbox Code Playgroud)
以下是CmakeLists.txt:
cmake_minimum_required(VERSION 3.5)
# Find python and Boost - both are required dependencies
find_package(PythonLibs 2.7 REQUIRED)
find_package(Boost COMPONENTS python REQUIRED)
# Without this, any build libraries automatically have names "lib{x}.so"
set(CMAKE_SHARED_MODULE_PREFIX "")
# Add a shared module - modules are intended to be imported at runtime.
# - This is where …Run Code Online (Sandbox Code Playgroud) boost-python ×10
c++ ×8
python ×7
binding ×1
cmake ×1
compilation ×1
itk ×1
java ×1
numpy ×1
python-3.2 ×1
python-3.x ×1
swig ×1