[英]Calling complicated C++ functions in Python (linux)
I have some functions in C++ source, declared like this: 我在C ++源代码中有一些函数,声明如下:
extern "C" {
int32_t comp_ip_long(const std::vector<EachColumn>& in, std::vector<EachColumn>& out);
}
The C++ code is compiled into xxx.so (linux shared object) and I want to call the function in Python. C ++代码被编译为xxx.so(Linux共享对象),我想在Python中调用该函数。 notice that I cannot modify the C++ code, so something like
boost::python
is not accessable. 请注意,我无法修改C ++代码,因此无法访问
boost::python
类的东西。
I've tried ctypes.CDLL, but I don't know how to pass the complicated argument to xxx.so? 我已经尝试过ctypes.CDLL,但是我不知道如何将复杂的参数传递给xxx.so?
PS: PS:
I've given a .so with some functions (with the above parameter type, but function names are unknown), the function name and parameters are input by user. 我给了.so一些函数(具有上述参数类型,但函数名称未知),函数名称和参数由用户输入。
I believe that you need helper glue functions declared as extern "C"
to construct (ie initialize) and fill your std::vector<EachColumn>
and have these helper functions called from Python. 我相信您需要使用声明为
extern "C"
帮助程序粘合函数来构造(即初始化)并填充std::vector<EachColumn>
并从Python中调用这些帮助程序函数。
Perhaps 也许
typedef std::vector<EachColumn> columnvect_t;
extern "C" columnvect_t *new_vect()
{ return new columnvect_t; };
extern "C" void del_vect(columnvect_t*vec)
{ delete vec; };
extern "C" void pushback_vect(columnvect_t* vec, EachColumn* col)
{ vec->push_back(*col); };
and likewise for your EachColumn
class. 同样适用于
EachColumn
类。
Maybe you need to make a glue library linked to the C++ library and dlopen
-ed by Python 也许您需要制作一个链接到C ++库并由python
dlopen
绑定的胶水库
Basically, Python is more C friendly than C++ friendly (so you need to make C++ glue code feeling like C for Python). 基本上,Python比C ++更友好C(因此,您需要使C ++粘合代码感觉像C for Python)。 Be careful that no C++ exception throwing crosses the Python interpreter (so catch all of them inside your glue functions)
请注意,没有C ++异常抛出会越过Python解释器(因此请在您的粘合函数中捕获所有异常)
If the C or C++ code is huge, you might consider customizing GCC to perhaps help in generating such glue code, either with MELT or with D.Malcom's GCC python Plugin . 如果C或C ++代码庞大,则可以考虑使用MELT或D.Malcom的GCC python插件自定义GCC,以帮助生成此类粘合代码。 But this takes time.
但这需要时间。
You can't call it from ctypes, you need at least to warp the function inside C so you could call it from Python. 您不能从ctypes调用它,至少需要在C内部扭曲函数,以便可以从Python调用它。
I don't know the details of your function but for example if you have such this C++ code: 我不知道您的函数的详细信息,但是例如,如果您具有以下C ++代码:
#include <iostream>
class Foo {
int bar;
public:
Foo(int bar) : bar(bar) {}
int getBar() const {
return bar;
}
void setBar(int bar) {
this->bar = bar;
}
void doSomething() const {
std::cout << bar << std::endl;
}
};
you can warp int this way: 你可以这样扭曲int:
// previous code here +
#define CAST_FOO(x) (static_cast<Foo *>(x))
#ifndef FOO_DEBUG
extern "C" {
#endif
void* foo_new(int bar) {
return static_cast<void*>(new Foo(bar));
}
int foo_get_bar(void *foo) {
return CAST_FOO(foo)->getBar();
}
void foo_set_bar(void *foo, int bar) {
CAST_FOO(foo)->setBar(bar);
}
void foo_do_something(void* foo) {
CAST_FOO(foo)->doSomething();
}
void foo_destroy(void* foo) {
delete CAST_FOO(foo);
}
#ifndef FOO_DEBUG
};
#endif
#ifdef FOO_DEBUG
int main(int argc, char **argv) {
void* foo = foo_new(10);
foo_do_something(foo);
foo_set_bar(foo, 20);
foo_do_something(foo);
foo_destroy(foo);
return 0;
}
#endif
now it should be callable from ctypes, and from C also. 现在应该可以从ctypes和C调用它。
$ g++ -Wall foo.cpp -DFOO_DEBUG
$ ./a.out
10
20
$ g++ -Wall foo.cpp -shared -o foo.so
$ python
>>> from ctypes import *
>>>
>>> so = cdll.LoadLibrary('foo.so')
>>> foo = so.foo_new(10)
>>>
>>> so.foo_do_something(foo)
10
>>> so.foo_set_bar(foo, 20)
>>> so.foo_do_something(foo)
20
>>> so.foo_destroy(foo)
>>>
A bit more work but maybe worth it in the long run is to use Boost.Python 需要做更多的工作,但从长远来看,值得使用Boost.Python
Example taken from the boost documentation: 从boost文档中获取的示例:
Following C/C++ tradition, let's start with the "hello, world". 遵循C / C ++的传统,让我们从“你好,世界”开始。 A C++ Function:
C ++函数:
char const* greet()
{
return "hello, world";
}
can be exposed to Python by writing a Boost.Python wrapper: 可以通过编写Boost.Python包装器暴露给Python:
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
That's it. 而已。 We're done.
大功告成 We can now build this as a shared library.
现在,我们可以将其构建为共享库。 The resulting DLL is now visible to Python.
现在,生成的DLL对Python可见。 Here's a sample Python session:
这是一个示例Python会话:
>>> import hello_ext
>>> print hello_ext.greet()
hello, world
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.