c向python注册函数_一个简单的注册c函数到python的包装器

这几天继续研究了一下python,顺便看了一下如何注册c的函数到python,这方面网上的东西已经很多了,就不详细说明了。反正大概就是把要注册的函数写成

PyObject* Fun(PyObject* self, PyObject* args)

这样的形式,然后通过PyArg_ParseTuple从python中取出参数传递给c函数,然后通过Py_BuildValue把c函数的返回值返回给python。

所以对于一个形式如 int DoFun(int)类型的c函数,我们需要做的就是

PyObject* Fun(PyObject* self, PyObject* args)

{

int arg;

PyArg_ParseTuple("i", &arg);

int ret = DoFun(arg);

return Py_BuildValue("i", ret);

}

如果只有一个两个函数那还好,万一函数很多,怎么办,难道我们要每个函数都这么写,我觉得这个工作量比较大,我是个懒惰的人(呵呵,通常程序员都是挺懒的),所以对于这种事情,我希望只通过一个函数RegFun就搞定了,就像我以前写的注册c函数到lua一样的。

首先就是考虑一个调用函数,他具有如下的形式

template

static PyObject* CallFun(PyObject* self, PyObject* args)

{

string strArgType;

string strRetType;

P1 p1;

ParseType(strArgType);

PyArg_ParseTuple(args, strArgType.c_str(), &p1);

ParseType(strRetType);

Ret ret = func(p1);

return Py_BuildValue(strRetType.c_str(), ret);

}

其中ParseType是根据不同的模板参数得到参数的类型表示,如ParseType的话strArgType就会添加一个"i"到参数字串上面。

如果写成上面的那种形式,那么我们对于任何形如 Ret (*pFun)(Param )类型的函数都能够注册给python了,当然,这里面的Ret和Pram必须得是一般类型,不支持类和结构,以及除了char*之外的指针。

但是这样有一个问题,就是万一如果我们的函数返回值为void,我们就需要重新定义CallFun了

内部结构如下:

string strArgType;

P1 p1;

ParseType(strArgType);

PyArg_ParseTuple(args, strArgType.c_str(), &p1);

func(p1);

return Py_BuildValue("");

于是我们就需要对模板进行偏特化处理,也就是把Ret换成void,但是现在c++的编译器是不支持函数模板的偏特化的,只支持函数模板的重载。那么如何解决呢?我们可以定义一个注册类

template

class CCallFun

{

public:

template

static PyObject* CallFun(PyObject* self, PyObject* args)

{

string strArgType;

string strRetType;

P1 p1;

ParseType(strArgType);

PyArg_ParseTuple(args, strArgType.c_str(), &p1);

ParseType(strRetType);

Ret ret = func(p1);

return Py_BuildValue(strRetType.c_str(), ret);

}

};

然后进行void的特化

template<>

class CCallFun

{

public:

template

static PyObject* CallFun(PyObject* self, PyObject* args)

{

string strArgType;

P1 p1;

ParseType(strArgType);

PyArg_ParseTuple(args, strArgType.c_str(), &p1);

func(p1);

return Py_BuildValue("");

}

};

那么对于函数int DoFun(int)和void DoFun1(int),他们对应的注册函数就分别为

CCallFun::CallFun;

CCallFun::CallFun

然后我们注册给python

PyMethodDef PyMethod[3]

{

{"DoFun1", &CCallFun::CallFun, METH_VARARGS},

{"DoFun1", &CCallFun::CallFun, METH_VARARGS},

{NULL, NULL},

};

PyImport_AddModule("wr")

Py_InitModule("wr", PyMethod)

然后我们在python里面

import wr

wr.DoFun(10)

wr.DoFun1(11)

这样就行了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值