一个简单的注册c函数到python的包装器
来源:互联网 发布:魔域名字大全 编辑:程序博客网 时间:2024/06/06 05:42
这几天继续研究了一下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<typename Ret, typename P1, typename Func, Func func>
static PyObject* CallFun(PyObject* self, PyObject* args)
{
string strArgType;
string strRetType;
P1 p1;
ParseType<P1>(strArgType);
PyArg_ParseTuple(args, strArgType.c_str(), &p1);
ParseType<Ret>(strRetType);
Ret ret = func(p1);
return Py_BuildValue(strRetType.c_str(), ret);
}
其中ParseType是根据不同的模板参数得到参数的类型表示,如ParseType<int>的话strArgType就会添加一个"i"到参数字串上面。
如果写成上面的那种形式,那么我们对于任何形如 Ret (*pFun)(Param )类型的函数都能够注册给python了,当然,这里面的Ret和Pram必须得是一般类型,不支持类和结构,以及除了char*之外的指针。
但是这样有一个问题,就是万一如果我们的函数返回值为void,我们就需要重新定义CallFun了
内部结构如下:
string strArgType;
P1 p1;
ParseType<P1>(strArgType);
PyArg_ParseTuple(args, strArgType.c_str(), &p1);
func(p1);
return Py_BuildValue("");
于是我们就需要对模板进行偏特化处理,也就是把Ret换成void,但是现在c++的编译器是不支持函数模板的偏特化的,只支持函数模板的重载。那么如何解决呢?我们可以定义一个注册类
template<typename Ret>
class CCallFun
{
public:
template<typename P1, typename Func, Func func>
static PyObject* CallFun(PyObject* self, PyObject* args)
{
string strArgType;
string strRetType;
P1 p1;
ParseType<P1>(strArgType);
PyArg_ParseTuple(args, strArgType.c_str(), &p1);
ParseType<Ret>(strRetType);
Ret ret = func(p1);
return Py_BuildValue(strRetType.c_str(), ret);
}
};
然后进行void的特化
template<>
class CCallFun<void>
{
public:
template<typename P1, typename Func, Func func>
static PyObject* CallFun(PyObject* self, PyObject* args)
{
string strArgType;
P1 p1;
ParseType<P1>(strArgType);
PyArg_ParseTuple(args, strArgType.c_str(), &p1);
func(p1);
return Py_BuildValue("");
}
};
那么对于函数int DoFun(int)和void DoFun1(int),他们对应的注册函数就分别为
CCallFun<int>::CallFun<int, int(*)(int), &DoFun>;
和
CCallFun<void>::CallFun<int, void(*)(int), &DoFun1>
然后我们注册给python
PyMethodDef PyMethod[3]
{
{"DoFun1", &CCallFun<int>::CallFun<int, int(*)(int), &DoFun>, METH_VARARGS},
{"DoFun1", &CCallFun<void>::CallFun<int, void(*)(int), &DoFun1>, METH_VARARGS},
{NULL, NULL},
};
PyImport_AddModule("wr")
Py_InitModule("wr", PyMethod)
然后我们在python里面
import wr
wr.DoFun(10)
wr.DoFun1(11)
这样就行了。
具体的代码请参照
http://code.google.com/p/tangliu/downloads/list
里面的ScriptPython.rar,不过这个版本是在vc8.0下面写的,linux下面没有经过测试。
- 一个简单的注册c函数到python的包装器
- 一个简单的注册c函数到lua的包装器
- python logging 的一个简单的包装
- python logging 的一个简单的包装
- 一个简单的 JDBC 包装器
- 一个简单的 JDBC 包装器
- 一个简单的 JDBC 包装器
- 一个简单的 JDBC 包装器
- python调用c函数的一个简单实例
- mysql 的一个简单的包装类
- 一个简单的libmad包装类
- 一个简单的libmad包装类
- 一个简单的libmad包装类
- 一个简单的注册页面
- 一个简单的注册框架
- Python次位面——用Greenlet包装一个会阻塞的函数
- 【C】一个简单的函数调用
- oracle OCCI 的一个简单的包装类的实现
- DOS命令大全
- mini2440的bootloader制作
- s60按键处理模型
- 我所理解之“网络”
- 数据库设计中常见表结构的设计技巧
- 一个简单的注册c函数到python的包装器
- 结构型模式之五---Facade
- 无聊
- UrlReWriter 使用经验小结
- hard code & hard working & hard night
- 浅谈适配器设计模式与观察者设计模式
- Should I use SAX or DOM? (Posted May 23rd, 1999 by Nazmul)
- 车载无线自组织网络的介质访问控制协议研究
- 在ATL DLL中实现在窗口中使用CDockablePane