zoukankan      html  css  js  c++  java
  • 巧用 python 脚本控制你的C程序

    python是一门艺术语言,除了开发桌面程序,还能够开发网络应用,数据库应用,还可以代替shell编写一些的实用脚本,本文主要讲述了如何利用 python 程序控制你的 C 程序的行为。

    作为例子,本文将用 python 和 C 语言来编写示例代码,同时也会顺便介绍一下 利用 C 语言扩展 python的方法,最后会给出完整的 C 编写 python 模块的源码。

    首先考虑以下应用:假设你需要在项目中实现字符串排序比较的功能,但是事先并不确定应该如何排序(再次假设一下,如果某字符串中如果出现了 “aaa”, "bbb" 这样的子串,就将该字符串排在靠后的位置),此时如果用 C 语言实现了预定义的排序功能,那么万一某天需要改变字符串排序行为,就必须重新编写 C 程序的实现,并且再次编译项目,这样会浪费大量的精力,相反,如果将字符串排序的功能用 python 代码控制,即如何排序由python程序定义,这样将大大提高程序的灵活性。

    以下就是示例程序,程序由 python 脚本和 C 编译的 python 模块组成,python 实现字符串比较功能,为了简化期间,本文只是先两个字符串大小的比较(用于说明 python控制程序行为已经足够),程序采用回调函数实现,完整代码如下:

    python模块:

    /*
    * =====================================================================================
    *
    * Filename: ext.c
    *
    * Description:
    *
    * Version: 0.1.0
    * Created: 09/16/2011 05:44:40 PM
    * Revision: r1
    * Compiler: gcc
    *
    * Author: Fu Haiping <haipingf@gmail.com>
    * Company: ICT
    *
    * =====================================================================================
    */

    #include
    <Python.h>

    static PyObject *my_callback = NULL;

    static PyObject *
    _set_callback(PyObject
    *self, PyObject *args)
    {
    PyObject
    *result = NULL;
    PyObject
    *temp;
    if (PyArg_ParseTuple(args, "O", &temp)) {
    if (!PyCallable_Check(temp)) {
    PyErr_SetString(PyExc_TypeError,
    "parameter must be callable");
    return NULL;
    }
    Py_XINCREF(temp);
    /* Add a reference to new callback */
    Py_XDECREF(my_callback);
    /* Dispose of previous callback */
    my_callback
    = temp; /* Remember new callback */
    /* Boilerplate to return "None" */
    Py_INCREF(Py_None);
    result
    = Py_None;
    }
    return result;
    }

    staticint _compare(constchar*a, constchar*b)
    {
    long ret;
    PyObject
    *arglist;
    PyObject
    * result = NULL;
    arglist
    = Py_BuildValue("(ss)", a, b);
    result
    = PyEval_CallObject(my_callback, arglist);
    ret
    = PyInt_AsLong(result);
    if (result == NULL)
    return-1;
    Py_DECREF(result);
    return ret;
    }

    void compare(constchar*a, constchar*b)
    {
    if (_compare(a, b) >0) {
    printf(
    "arg1 is greater than arg2\n");
    }
    elseif (_compare(a, b) <0) {
    printf(
    "arg1 is NOT greater than arg2\n");
    }
    else {
    printf(
    "arg1 is equal to arg2\n");
    }
    }

    static PyObject* _compare_callback(PyObject *self, PyObject *args)
    {

    constchar*a = NULL, *b = NULL;
    if (!PyArg_ParseTuple(args, "ss", &a, &b)) {
    return NULL;
    }
    compare(a, b);
    Py_INCREF(Py_None);
    return Py_None;
    }

    static PyMethodDef
    extMethods[]
    = {
    {
    "setcmp", _set_callback, METH_VARARGS},
    {
    "compare", _compare_callback, METH_VARARGS},
    {NULL, NULL}
    };

    void initext()
    {
    Py_InitModule(
    "ext", extMethods);
    }

    setup.py 文件:

    from distutils.core import setup, Extension
    module1
    = Extension('ext',
    sources
    = ['ext.c'])
    setup (name
    ='ext',
    version
    ='1.0',
    description
    ='This is a demo package',
    ext_modules
    = [module1])

    执行过程:

    $ python
    Python
    2.6.6 (r266:84292, Sep 152010, 15:52:39)
    [GCC
    4.4.5] on linux2
    Type
    "help", "copyright", "credits"or"license"for more information.
    >>>import ext
    >>>def compare(a, b):
    ...
    if (a > b):
    ...
    return-1
    ...
    if (a < b):
    ...
    return1
    ...
    if (a ==b):
    ...
    return 0
    ...
    >>> setcmp(compare)
    Traceback (most recent call last):
    File
    "<stdin>", line 1, in<module>
    NameError: name
    'setcmp'isnot defined
    >>> ext.setcmp(compare)
    >>> ext.compare("aaa", "bbb")
    arg1
    is greater than arg2
    >>>

    上述执行过程中,我们利用了 pythoon 的 compare函数,该函数实现字符串的比较,如果 a > b, 返回 -1,a < b, 返回1,  a == b, 返回0, 这和我们平常的比较方式相反,所以最后的结果中我们可以看到比较 "aaa", "bbb" 时,"aaa" 会比 “bbb” 大。

    如果使用 python 定义我们常规的字母排序的比较函数,会看到如下执行结果:

    >>>def compare_ex(a, b):
    ...
    if (a > b):
    ...
    return1
    ...
    if (a < b):
    ...
    return-1
    ...
    if (a == b):
    ...
    return 0
    ...
    >>> ext.setcmp(compare_ex)
    >>> ext.compare("aaa", "bbb")
    arg1
    is NOT greater than arg2

    此时,"aaa" 就比 "bbb" 小。

    结论,以上只是一个小小的尝试,python的灵活性远远不止如此,Haippy会继续探索 python的一些有趣的特性和使用方法,请关注本博客后续文章。:-) 

  • 相关阅读:
    基础知识漫谈(5):应用面向对象来分析“语言”
    【线段树】BZOJ2752: [HAOI2012]高速公路(road)
    【树状数组】BZOJ3132 上帝造题的七分钟
    【AC自动机】Lougu P3796
    【Splay】bzoj1500(听说此题多码上几遍就能不惧任何平衡树题)
    【fhq Treap】bzoj1500(听说此题多码上几遍就能不惧任何平衡树题)
    【可持久化线段树】POJ2104 查询区间第k小值
    【RMQ】洛谷P3379 RMQ求LCA
    【倍增】洛谷P3379 倍增求LCA
    【网络流】POJ1273 Drainage Ditches
  • 原文地址:https://www.cnblogs.com/haippy/p/2179902.html
Copyright © 2011-2022 走看看