文档章节

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

siddontang
 siddontang
发布于 2014/05/11 16:31
字数 801
阅读 181
收藏 0

这几天继续研究了一下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下面没有经过测试。

© 著作权归作者所有

siddontang
粉丝 58
博文 41
码字总数 49108
作品 4
珠海
私信 提问
TensorFlow架构与设计:会话生命周期

TensorFlow的系统结构以C API为界,将整个系统分为「前端」和「后端」两个子系统: 前端系统:提供编程模型,负责构造计算图; 后端系统:提供运行时环境,负责执行计算图。 前端系统主要扮演...

刘光聪
2017/03/04
0
0
通过 Python 装饰器实现DRY(不重复代码)原则

Python装饰器是一个消除冗余的强大工具。随着将功能模块化为大小合适的方法,即使是最复杂的工作流,装饰器也能使它变成简洁的功能。 例如让我们看看Django web框架,该框架处理请求的方法接...

renwofei423
2013/07/17
4.8K
8
Python - 装饰器使用过程中的误区

曾灵敏 — APRIL 27, 2015 装饰器基本概念 大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,, 等。 Python语言本...

OneAPM1
2015/05/08
39
1
用 Numba 加速 Python 代码,变得像 C++ 一样快

(给Python开发者加星标,提升Python技能) 英文:Puneet Grover,译:zxdefying,艾凌风 校稿 整理:Python开发者(id:PythonCoder) 目录 介绍 为什么选择 Numba? Numba 是如何工作的? ...

Python开发者
05/15
0
0
转载:唐磊的个人博客《python中decorator详解》【转注:深入浅出清晰明了】

转载请注明来源:唐磊的个人博客《python中decorator详解》 前面写python的AOP解决方案时提到了decorator,这篇文章就详细的来整理下python的装饰器——decorator。 python中的函数即objects...

laugh2last
2015/08/17
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周五乱弹 ——不知道假装开心,装的像么

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :天黑了 你很忧愁, 你说世界上, 找不到四块五的妞, 行走在凌晨两点的马路上, 你疲倦地拿着半盒黄鹤楼。#今日歌曲推荐# 《四块...

小小编辑
今天
2.1K
16
64.监控平台介绍 安装zabbix 忘记admin密码

19.1 Linux监控平台介绍 19.2 zabbix监控介绍 19.3/19.4/19.6 安装zabbix 19.5 忘记Admin密码如何做 19.1 Linux监控平台介绍: 常见开源监控软件 ~1.cacti、nagios、zabbix、smokeping、ope...

oschina130111
昨天
69
0
当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
昨天
32
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
昨天
116
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
昨天
31
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部