• 如何实现Python调用C代码--python与C之间如何通信(swig)


    转载: https://www.zhihu.com/question/23003213

    1. C代码如何调用Python

    1.1 test

    #include <Python.h>    
                           
    int main(int argc, char *argv[])
    {
        Py_SetProgramName(argv[0]);
        Py_Initialize();   
        
        PyRun_SimpleString("print ('Hello Python!')
    ");
    
        Py_Finalize();
    
        return 0;
    
    }

    Linux下执行:

    gcc -Wall cpython01.c -o cpython01.out -I/usr/include/python2.7 -lpython2.7

    注意是Python2.7不是python3...不然好像报错....

    1.2 C调用Python函数

    great_module.py

    #!/usr/bin/python3     
    #-*- coding:utf-8 -*-  
    
    def great_function(a):
        return a + 1     

    include_module_from_py.c

    #include <stdio.h>
    #include <Python.h>
    
    int include_module_from_py(int a)
    {
        int res = 0;
        PyObject *pModule, *pFunc;
        PyObject *pArgs, *pValue;
    
        //import great_module.py 
        pModule = PyImport_Import(PyString_FromString("great_module"));  //
    
        //great_module.great_function(args)
        pFunc = PyObject_GetAttrString(pModule, "great_function");
    
        //build args
        pArgs = PyTuple_New(1);                           //Pyxxx_new录创建类型为xxx的变量
        PyTuple_SetItem(pArgs, 0, PyInt_FromLong(a));     //若a为tuple, 则a[i]=b对应于 PyTuple_SetItem(a, i, b)
    
        //call
        pValue = PyObject_CallObject(pFunc, pArgs);
    
        res = PyInt_AsLong(pValue);   
    
        return res;
    }
    
    int main()
    {
    
        Py_Initialize();
    
        printf("res = %d
    ", include_module_from_py(3));
    
        Py_Finalize();
    
        return 0;
    }

    运行时,需要先: 

    export PYTHONPATH=.:$PYTHONPATH

    编译:

    gcc -Wall include_module_from_py.c -o include_module.out -I/usr/include/python2.7 -lpython2.7

    2. python调用C/C++

    great_module.c
    #include <stdio.h>
    #include <Python.h>
    
    int great_function(int a)
    {
        return a + 1;
    }
    
    static PyObject * _great_function(PyObject *self, PyObject *args)
    {
        int _a; 
        int res;
    
        //负责将Python的参数转换为C的参数
        if (!PyArg_ParseTuple(args, "i", &_a))
        {   
            return NULL;
        }   
    
        res = great_function(_a);
    
        return PyLong_FromLong(res);
    
    }
    
    //导出表, 负责告诉Python这个模块有哪些函数可以被Python调用
    static PyMethodDef GreateModuleMethods[] = { 
        {   
            "great_function",         // 函数名
            _great_function,          // 包裹函数
            METH_VARARGS,             // 参数变长 
            ""                        // 说明性文字
        },  
        { NULL, NULL, 0, NULL }       //总是如此 
    };
    
    //导出函数, 名字: module名称+前缀init
    PyMODINIT_FUNC initgreat_module()
    {
    
        (void) Py_InitModule("great_module", GreateModuleMethods);
    }
    gcc -fPIC -shared great_module.c -o great_module.so -I/usr/include/python2.7 -lpython2.7

    3. ctypes: Python调用C

    #include <stdio.h>
    
    int add_int(int a, int b)
    {
        return a + b;
    }
    
    double add_double(double a, double b)
    {
        return a + b;
    }
    gcc -shared -Wl,-soname,adder -o adder.so -fPIC add.c
    #!/usr/bin/python3
    #-*- coding:utf-8 -*-
    
    from ctypes import *
    
    
    adder = CDLL('./adder.so')
    
    
    res_int = adder.add_int(4, 5)
    print("4 + 5 = %d " % (res_int))
    
    a = c_double(5.5)
    b = c_double(4.1)
    
    add_double = adder.add_double
    add_double.restype = c_double 
    print("5.5 + 4.1 = ", str(add_double(a, b)))

    工作中用了之后, 想想看还是用ctypes方便点....工程生成.so动态链接库, 然后直接在Python里导入. 

    最好是在C代码中, 将需要的功能接口写的易调用点!! 然后Python也不需要传很多的参数, 直接获取一个结果等等...

    4. 使用SWIG使Python调用C/C++ 

    example.h

    #include <iostream>
    using namespace std;
    
    class Example {
        public:
            void say_hello();
        
    };

    example.cpp

    #include "example.h"
    
    void Example::say_hello()
    {
        cout << "hello
    ";
    }

    example.i

    %module example
    %{
    #include "example.h"
    %}
    %include "example.h"

    setup.py

    #!/usr/bin/python3
    #-*- coding:utf-8 -*-
    
    """
    setup.py file for SWIG C++/Python example
    """
    from distutils.core import setup, Extension
    
    example_module = Extension('_example',
        sources=['example.cpp', 'example_wrap.cxx',],
    )
    
    setup (
        name = 'example',
        version = '0.1',
        author = "douzi",
        description = """Simple swig C++/Python example""",
        ext_modules = [example_module],
        py_modules = ["example"],
    )

    然后使用:

    swig -c++ -python example.i
    python3 setup.py build_ext --inplace

     https://blog.csdn.net/gxt_gy/article/details/50341215

  • 相关阅读:
    〖Linux〗Kubuntu设置打开应用时就只在打开时的工作区显示
    〖Linux〗Kubuntu, the application 'Google Chrome' has requested to open the wallet 'kdewallet'解决方法
    unity, dll is not allowed to be included or could not be found
    android check box 自定义图片
    unity, ios skin crash
    unity, Collider2D.bounds的一个坑
    unity, ContentSizeFitter立即生效
    类里的通用成员函数应声明为static
    unity, Gizmos.DrawMesh一个坑
    直线切割凹多边形
  • 原文地址:https://www.cnblogs.com/douzujun/p/10738959.html
Copyright © 2020-2023  润新知