我使用 c/python api 将我的类绑定(bind)到 python。 我制作了新模块并成功绑定(bind)了类类型。 c/python api 具有 PyMethodDef 结构来将函数绑定(bind)到 python 类。
PyMethodDef pyMethodDef = { "PyFunction", PYFunction, METH_KEYWORDS |
METH_VARARGS , "PyFunction" };
PyObject *pFunc = PyCFunction_New(&pyMethodDef, NULL);
PyObject *pMethod = PyInstanceMethod_New(pFunc);
int result = PyDict_SetItemString(pPyClassDict, pyMethodDef.ml_name,
pMethod);
但是,有一个糟糕的规则,绑定(bind)函数必须有 PyObject* 返回类型,并且它必须有 2 个 PyObject* 参数。
PyObject* PYFunction(PyObject* self, PyObject* args)
{
char *s = "Hello from C!";
return Py_BuildValue("s", s);
}
所以我不能像这样绑定(bind)我的类和成员函数。
class Position
{
int x;
int y;
public:
Position() {x = 0; y = 0}
~Potition() { }+
void SetZero()
{
x = 0, y = 0
}
}
像下面这样改变所有成员函数的签名是不可能的。 因为实际上我有很多类要绑定(bind)。
PyObject* method(PyObject*, PyObject*)
那么 boost python 将是一个解决方案,但它太大而无法使用。 我只需要 python binder,它太难用了。
有什么方法可以仅使用纯 c/python api 将 c++ 成员函数(方法)绑定(bind)到 python 吗? (PyMethodDef 结构的第二个成员是 PyCFunction 类型...)
最佳答案
要使简单的包装器快速工作,同时只需编写很少的胶水,那么 SWIG 是您的最佳选择。
假设你想包装example.{h,cpp}
,通常你需要写的是:
/* File: example.i */
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include example.h
%module example
告诉 SWIG 生成一个名为“example”的模块#include "example.h"
使您的 C++ 函数定义在example.i
中可用
%include example.h
告诉 SWIG 导出它直接在example.h
中找到的每个函数和类定义。
然后运行:
swig -c++ -python example.i # generates example.py and example_wrap.cxx
g++ -c -fPIC example.cxx
g++ -c -fPIC example_wrap.cxx -I /usr/include/python3.5
g++ -shared example.o example_wrap.o -o _example.so
你就完成了。 (作为引用,我使用的是 python 3.5 和 SWIG 3.0)
函数重载
一个常见的陷阱是,如果您有 SWIG 无法消除歧义的重载函数(例如,它们重载整数类型 [foo(int)
vs foo(short)
], float 点类型,或指针与引用 [Foo*
与 Foo&
])。您可以在 example.i
中添加忽略或重命名指令,以帮助它了解要忽略哪些函数或如何公开它们。
例如,给定:
/* File: example.h */
int add(int a, int b);
short add(short a, short b);
long long add(long long a, long long b);
double add(double a, double b);
您可以将以下内容添加到您的example.i
:
%ignore add(short, short);
%rename("add_long_long") add(long long, long long);
然后你可以像这样使用它:
>>> import example
>>> example.add(1, 2) # add(int, int)
3
>>> example.add(1.5, 2) # add(double, double)
3.5
>>> example.add_long_long(1, 2) # add(long, long)
3
>>> example.add_long_long(1 << 30, 1 << 30) # add(long, long)
2147483648
>>> example.add(1 << 30, 1 << 30) # add(int, int)
-2147483648
关于python - 如何仅使用 c/python api 将 c++ 成员函数绑定(bind)到 python?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50561318/