zoukankan      html  css  js  c++  java
  • 使用swig为python添加c扩展总结

    转载:http://blog.csdn.net/chgaowei/article/details/7467632

    1、  可以使用swig来创建c 的扩展程序,非常方便。目前没有时间研究内部机制,先暂时使用,后面在研究吧。

    2、  swig使用步骤:为库的头文件建立.i文件:

    %{

    /* Includes theheader in the wrapper code */

    #include"code.h"

    #include"sip.h"

    %}

     /* Parse theheader file to generate wrappers */

    %include"code.h"

    %include"sip.h"

    3、  使用swig命令生成py脚本及对应的C文件:swig –python sip.i。

    4、  将生成的c源文件放到c扩展库中进行编译。

    5、  这里有一个要注意:生成的动态链接库,必须是_sip.so,否则无法调用。swig是写死的。_sip.so需要拷贝到:/usr/local/lib/python2.7/site-packages/路径下。

    6、  Makefile文件中,对于库引用的其他的库,必须显示的指出,否则Python无法找到对应的库。

    7、  如何在c的扩展库中调用Python的函数——将c扩展库的回调函数设置为python函数:

    swig是不支持直接在c的扩展库中调用Python函数的。它只支持将C的接口作为回调函数设置给c的库。

    实现这个功能需要利用Python的c API和ctypes来实现。

    Python c 的api包含一系列的函数:

    PyCallable_Check:检查对象是否可调用;

    PyArg_ParseTuple:解析参数列表,将Python参数解析为c;

    PyEval_CallObject:调用对象;

    Py_BuildValue:将c变量打包为Python的参数对象。

    好了,有这些就足够了。

    假设c库中有一个设置回调函数接口:

    void set_callback_fun(void(*fun)(int, int , int))

    {

    }

    下面是c扩展库中要添加的代码:

    //全局变量,保存Python中要回调的可调用对象。

    static PyObject*gCallbackFun = NULL;

     //调用上面函数设置的python脚本函数

    //Python可调用对象的转换函数,转化为C的调用方式

    static voidcallbacfun(int type,int chn,int dataType)

    {

        PyObject* pArgs = NULL;

        PyObject* pRetVal = NULL;

        int   nRetVal = 0;

         pArgs = Py_BuildValue("(i, i,i)", type, chn, dataType);//将c的参数转化为Python的参数对象

        pRetVal = PyEval_CallObject(gCallbackFun,pArgs);//调用Python的可调用对象。

        Py_DECREF(pArgs);

        Py_DECREF(pRetVal);

    }

     /// set_callback_fun函数的包装函数

    static PyObject*wrap_set_callback_fun(PyObject *dummy, PyObject *args)

    {

        PyObject *temp = NULL;

         if (PyArg_ParseTuple(args, "O:set_callback_fun",&temp)) {//获取Python对象

            if (!PyCallable_Check(temp)) {//检查对象是否可以调用

                PyErr_SetString(PyExc_TypeError,"parameter must be callable");

            }

        Py_XINCREF(temp);         /* Add a reference to new callback */

        Py_XDECREF(gCallbackFun); /* Dispose ofprevious callback */

        gCallbackFun = temp;       /* 保存回调对象 */

        }

          set_callback_fun(callbacfun);//注意,这里掉一下包,用一个C的函数注册到c库中。

           return Py_BuildValue("i",(gCallbackFun == NULL) ? 0 : 1);

    }

     注意:如果对象不可调用,会段错误。后面要解决一下。

     Python代码:

       CBFUNC  =CFUNCTYPE(c_int, c_int, c_int, c_int)//创建一个c函数类型的对象工厂,该函数返回值为int,有三个入参,都为int。

    callbakFunc = CBFUNC(pyFun)//根据Python可调用对象生成函数。

    set_callback_fun(callbakFunc)//设置回调函数

    注意:pyFun必须要有返回值。否则会报异常。

    另外,我发现,不用CFUNCTYPE来生产c回调函数,直接用pyFun,也是可以的。至于区别,后面在研究一下吧,要写代码了。

            几个异常问题:1、一个可以使用CFUNCTYPE,但是一个一使用它就段错误。2、回调函数可以不返回值,也是可以的。但是一个不返回就不可以。

    在Python中使用c扩展时向C传递数组:

    8、  如果一个函数的参数是一个数组(指针),Python如何传递?下面的方法是可以直接传递列表。把这个加到.i文件中。

    %{

    static intconvert_darray(PyObject *input, int *ptr, int size) {

      int i;

      if (!PySequence_Check(input)) {

         PyErr_SetString(PyExc_TypeError,"Expecting a sequence");

          return 0;

      }

      if (PyObject_Length(input) != size) {

          PyErr_SetString(PyExc_ValueError,"Sequencesize mismatch");

          return 0;

      }

      for (i =0; i < size; i++) {

          PyObject *o =PySequence_GetItem(input,i);

          if (!PyFloat_Check(o)) {

             Py_XDECREF(o);

            PyErr_SetString(PyExc_ValueError,"Expecting a sequence offloats");

             return 0;

          }

          ptr[i] = PyFloat_AsDouble(o);

          Py_DECREF(o);

      }

      return 1;

    }

    %}

    %typemap(in) int[ANY](int temp[$1_dim0]) {

       if (!convert_darray($input,temp,$1_dim0)) {

          return NULL;

       }

       $1 = &temp[0];

    }

    9、  如果一个结构体中有一个int类型数组,应该如何赋值?

    在.i中增加下面代码:

    %include"carrays.i"

    %array_class(int,intArray);

    在Python中申请数组:

    a = intArray(10),将A复制给数组成员即可。

  • 相关阅读:
    第1章 CLR的执行模型
    第19章 可空值类型
    Servlet 3.0 特性
    java代码逆序输出再连篇
    java代码逆序输出数字
    java代码实现从键盘输入编号,输出价格,并且不再编号内的,无效输入!!!!
    java代码,实现输入编号,输出对应水果的单价~~~~
    java.输入水果的编号,求它对应的单价
    java.控制次数,每一组数都要计算。所以有个嵌套
    java练习,,,从键盘输入次数,输出最大值,和
  • 原文地址:https://www.cnblogs.com/ldjhust/p/3448763.html
Copyright © 2011-2022 走看看