我在C ++源代码中有一些函数,声明如下:
extern"C" {
int32_t comp_ip_long(const std::vector& in, std::vector& out);
}
C ++代码被编译成xxx.so(linux共享对象),我想在Python中调用该函数。 请注意,我无法修改C ++代码,因此像boost::python这样的东西是不可访问的。
我试过ctypes.CDLL,但我不知道如何将复杂的参数传递给xxx.so?
PS:
我给了一个带有一些函数的.so(带有上面的参数类型,但函数名称未知),函数名和参数由用户输入。
从长远来看,更多的工作但也许值得使用Boost.Python
从boost文档中获取的示例:
遵循C / C ++传统,让我们从"你好,世界"开始吧。一个C ++函数:
char const* greet()
{
return"hello, world";
}
可以通过编写Boost.Python包装器来暴露给Python:
#include
BOOST_PYTHON_MODULE(hello_ext)
{
using namespace boost::python;
def("greet", greet);
}
而已。我们完成了。我们现在可以将其构建为共享库。现在可以看到生成的DLL。这是一个Python会话示例:
>>> import hello_ext
>>> print hello_ext.greet()
hello, world
你不能从ctypes调用它,你至少需要扭曲C中的函数,所以你可以从Python调用它。
我不知道你的函数的细节,但是例如,如果你有这样的C ++代码:
#include
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;
}
};
你可以这样扭曲:
// previous code here +
#define CAST_FOO(x) (static_cast(x))
#ifndef FOO_DEBUG
extern"C" {
#endif
void* foo_new(int bar) {
return static_cast(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
现在它应该可以从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)
>>>
我相信你需要声明为extern"C"的辅助粘合函数来构造(即初始化)并填充你的std::vector并从Python调用这些辅助函数。
也许
typedef std::vector 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); };
同样适合你的EachColumn课程。
也许你需要制作一个链接到C ++库的胶水库和Python的dlopen -ed
基本上,Python比C ++友好更友好(因此你需要使C ++的胶水代码感觉像C的Python)。注意没有C ++异常抛出Python解释器(所以在你的粘合函数中捕获所有这些)
如果C或C ++代码很大,您可以考虑自定义GCC,以帮助生成这样的粘合代码,无论是使用MELT还是使用D.Malcom的GCC python插件。但这需要时间。
您仍然需要添加C ++代码。 实际上功能名称是由其他人提供的,我根本不知道它。