zoukankan      html  css  js  c++  java
  • C与python的调用一(导入python模块与,获得函数与类)

    python是一门很优秀的脚本语言,语法简洁而清晰,具有丰富和强大的类库。它常被昵称为胶水语言,它能够很轻松的把用其他语言制作的各种模块。 但是python的界面设计我们并不是很熟悉(虽然他也有很多很好的且功能强大的类库,例如wxpython等,但是相比其他的GUI设计,我们可能更加 熟悉QT或者MFC,因此不太会选用python作为界面设计的工具),所以我们在很多情况下,很难在有界面需求的项目中使用python的GUI去设 计。但是这样并不意味着我们不能依靠python的高效,简洁去做一些东西,我们可以用python做一些模块,然后再其他的编程语言中去调用她,下面就 举例一些相关的函数。

     

        如果你在C代码中去调用python,那么你首先要做到就是初始化python环境。具体使用的函数如下为Py_Initialize()。当你 正确的将python环境初始化之后,就可以用最简单的一个CPython接口去跑一些脚本,该函数为PyRun_SimpleString(s),这个 函数大家一看就知道是用来干啥的了吧。使用该函数能够让你直接在参数里面写一些python,然后python环境就会调用这个函数,完成你所写的 python语句。例如PyRun_SimpleString("import tree"),使用这个语句,就能在C环境中使用python加载了 tree.py这个模块。

        接下来,我们就要获得模块中定义的一些函数,大家知道,python里面的模块里面会定义很多的函数,类。当我们在python中对相关模块进行 import之后就能够直接调用了,那么我们在C中要如何获得这些函数、类呢?这些函数,类又是些什么东西呢。这就涉及到python的一些基本机制了, 其实在python里面,一切的东西都是对象,他们有共同的基类PyObject,至于这个PyObject具体是什么,这里就不展开了。因此我们可以得 出一些思路,那既然一切都是PyObject,那么我们在C里面使用PyObject将函数与类接进来不就好了。

        现在让我们回到我们运行了PyRun_SimpleString("import tree"),此时我们已经在运行环境中加载了tree.py这个模块 了,那这个模块又是什么呢。根据上文,大家应该能猜到,没错,这个模块也是个以PyObject为基类的对象。此时对应的函数为 (PyObject *) PyImport_ImportModule(const char *name)或者 (PyObject *) PyImport_Import(PyObject *name)(两者的区别为,如果使用后者,你需要将模块的名称(通常是 char*)转换成PyObject对象),此时你就会得到一个类型为PyObject的moudle对象。

        对于这个moudle对象,这里就不卖关子了,它实际上是一个python中的特殊的dict对象,里面有各种包含了这个moudle中的所有的类函数等 信息。因此,从这个moudle中获得相关的类和函数就是手到擒来的事情了。首先我们将这个moudle返回成一个dict对象,使用的函数为 (PyObject *) PyModule_GetDict(PyObject *)然后就使用 (PyObject *) PyDict_GetItemString(PyObject *dp, const char *key)来获得相关的函数 与类。如果是类的话,那获得的只是一个类定义,我们还需要将其构造成对象,使用的接口为 (PyObject *) PyInstance_New(PyObject *, PyObject *,PyObject *)具体的函数这里就不展 开了,大家网上找找吧。

     

    下面是网上的一个代码,比较详细的说了这一系列过程,大家可以试一试,源网址找不到了,悲剧,就直接贴代码了:

    def hello(s):

        print "hello world"

        print s

     

    def arg(a, b):

        print 'a=', a

        print 'b=', b

        return a + b

     

    class Test:

        def __init__(self):

            print "init"

        def say_hello(self, name):

            print "hello,", name

            return name

     

     

     

     

    // pytest.cpp : 定义控制台应用程序的入口点。

    //

     

    #include "stdafx.h"

    #include <Python.h>

     

    int main(int argc, char* argv[])

    {

    //初始化python

    Py_Initialize();

     

    //定义python类型的变量

    PyObject *pModule = NULL;

    PyObject *pFunc = NULL;

    PyObject *pArg = NULL;

    PyObject *result = NULL;

    PyObject *pClass = NULL;

    PyObject *pInstance = NULL;

    PyObject *pDict = NULL;

     

    //直接运行python代码

    PyRun_SimpleString("print 'python start'");

     

    //引入模块

    pModule = PyImport_ImportModule("test_code");

    //获取模块字典属性

    pDict = PyModule_GetDict(pModule);

     

    //直接获取模块中的函数

    pFunc = PyObject_GetAttrString(pModule, "hello");

     

    //参数类型转换,传递一个字符串。将c/c++类型的字符串转换为python类型,元组中的python类型查看python文档

    pArg = Py_BuildValue("(s)", "hello charity");

     

    //调用直接获得的函数,并传递参数

    PyEval_CallObject(pFunc, pArg);

     

    //从字典属性中获取函数

    pFunc = PyDict_GetItemString(pDict, "arg");

    //参数类型转换,传递两个整型参数

    pArg = Py_BuildValue("(i, i)", 1, 2);

     

    //调用函数,并得到python类型的返回值

    result = PyEval_CallObject(pFunc, pArg);

    //c用来保存c/c++类型的返回值

    int c;

    //将python类型的返回值转换为c/c++类型

    PyArg_Parse(result, "i", &c);

    //输出返回值

    printf("a+b=%d\n", c);

     

    //通过字典属性获取模块中的类

    pClass = PyDict_GetItemString(pDict, "Test");

     

    //实例化获取的类

    pInstance = PyInstance_New(pClass, NULL, NULL);

    //调用类的方法

    result = PyObject_CallMethod(pInstance, "say_hello", "(s)", "charity");

    //输出返回值

    char* name=NULL;

    PyArg_Parse(result, "s", &name);   //这个函数的第二个参数相当扯淡,具体看下文的英文,类型使用字符来表示的,例如“s”代表

                                                            //str "i" 代表int,个人感觉相当扯淡

    printf("%s\n", name);

     

    PyRun_SimpleString("print 'python end'");

     

    //释放python

    Py_Finalize();

    getchar();

    return 0;

    }

     

     

    运行结果:

    python start

    hello world

    hello charity

    a= 1

    b= 2

    a+b=3

    init

    hello, charity

    charity

    python end

  • 相关阅读:
    FastReport合并多份报表为一份预览打印
    Delphi使用AcroPDF ActiveX显示PDF文件
    Delphi使用Zxing创建二维码
    TreeView和ListView数据库查询数据联动操作
    根据数据库查询结果动态创建控件(仿看板模式显示)
    GridView控件使用
    LayoutControl控件使用
    TreeListLookUpEdit控件使用
    Devexpress TreeList控件使用
    Asp.Net 5上传文件 (Core API方式)
  • 原文地址:https://www.cnblogs.com/highkgao/p/4713939.html
Copyright © 2011-2022 走看看