Mutual call between Python and C

Original website: https://www.cnblogs.com/chengxuyuancc/p/5355202.html

python and c call each other

 

Although Python has high development efficiency, its performance as a scripting language is not high. Therefore, in order to give consideration to development efficiency and performance, modules with high performance requirements are usually implemented in c or c + +, or Python scripts are run in c or c + + to process logic. The former is usually the implementation method of some modules in Python, The latter is common in server-side programs (realizing business expansion or Plugin functions) and game development (scripts only deal with logic). This paper mainly introduces how to realize the mutual call between Python and c by running Python script in c, and explains it by setting the same memory area through c and python script as an example.

 

preparation

In order to run Python scripts in c, you need to link the python virtual machine library when linking the program. The python virtual machine library is python27 in libs under the python installation directory Lib file. As for how to link the library into the program, you can google it yourself. Because some Python methods and data structures are used in c, you need to add the include directory under the python installation directory to the project include directory. Well, that's all you need to prepare, and then you can start to implement an example of setting a memory area.

 

Embedded python virtual machine

Embedding Python virtual machine in c is very simple. You only need to include Python at the beginning of the program H header file, and then call the next two paragraphs to initialize the python virtual machine instance.

1 Py_SetPythonHome("D:\Python27");
2 Py_Initialize();

  Py_ The setpython home function is used to set the python library path, that is, the python installation path, py_ The initialize function actually instantiates a python virtual machine, so that a python virtual machine is embedded in c.

 

Call python script

After initializing the python virtual machine, you can actually call the python script. The method of calling script module in c is divided into the following steps:

1. Use PyImport_ImportModule imports the footstep module;

2. Use PyObject_GetAttrString get module specific method information;

3. Use Py_VaBuildValue conversion input parameters;

4. Use PyObject_CallObject calls a specific method;

5. Use pyarg_ Return result of parse conversion method.

Since all the methods in the calling module of the above process are necessary, you can write a function to encapsulate the above five steps. The specific code is as follows:

 
int PyModuleRunFunction(const char *module, const char *function,
                        const char *result_format, void *result, const char *args_format, ...)
{

    PyObject *pmodule, *pfunction, *args, *presult;

    pmodule = PyImport_ImportModule(const_cast<char *>(module));
    if (!pmodule)
    {
        PyObject *type = PyErr_Occurred();
        if (type == PyExc_NameError)
        {
            PyErr_Clear();
            return 0;
        }

        PyError("PyModuleRunFunction");
        return -1;
    }

    pfunction = PyObject_GetAttrString(pmodule, const_cast<char *>(function));
    Py_DECREF(pmodule);
    if (!pfunction)
    {
        PyObject *type = PyErr_Occurred();
        if (type == PyExc_AttributeError)
        {
            PyErr_Clear();
            return 0;
        }

        PyError("PyModuleRunFunction");
        return -2;
    }

    if (pfunction == Py_None)
    {
        return 0;
    }

    va_list args_list;
    va_start(args_list, args_format);
    args = Py_VaBuildValue(const_cast<char *>(args_format), args_list);
    va_end(args_list);

    if (!args)
    {
        Py_DECREF(pfunction);
        return -3;
    }

    presult = PyObject_CallObject(pfunction, args);
    if (presult == 0)
    {
        PyError("PyModuleRunFunction");
        Py_XDECREF(pfunction);
        Py_XDECREF(args);
        return -1;
    }

    Py_XDECREF(pfunction);
    Py_XDECREF(args);

    return ConvertResult(presult, result_format, result);
}

 

With the above general function for calling methods in python module, we can directly call methods in python script, as follows:

1 PyModuleRunFunction("hello", "test", "", 0, "()");

In this way, we implemented the method of calling python in c. Now let's talk about how python calls methods in c.

 

Initialize the python module implemented by c

In order to invoke the method defined in c in Python script, we need to define a python module in c first, then import module in script, and finally use this module to indirectly call the method defined in c. For example, we define a memory area data through c and a function SetData and GetData for the memory area (code as follows). How do we invoke SetData and GetData functions in the script to manipulate data? In fact, the key problem is how to call SetData and GetData functions in script. If you can call these two functions in script, you can operate data naturally. Python solves this problem through modules.

 1 #define min(a,b)    (((a) < (b)) ? (a) : (b))
 2 
 3 char data[1024];
 4 
 5 void SetData(const char *str)
 6 {
 7     strncpy(data, str, min(strlen(str) + 1, 1024));
 8 }
 9 
10 const char *GetData()
11 {
12     return data;
13 }

There are specific steps to define a python module in c. the specific code is as follows:

 
int PyModuleRunFunction(const char *module, const char *function,
                        const char *result_format, void *result, const char *args_format, ...)
{

    PyObject *pmodule, *pfunction, *args, *presult;

    pmodule = PyImport_ImportModule(const_cast<char *>(module));
    if (!pmodule)
    {
        PyObject *type = PyErr_Occurred();
        if (type == PyExc_NameError)
        {
            PyErr_Clear();
            return 0;
        }

        PyError("PyModuleRunFunction");
        return -1;
    }

    pfunction = PyObject_GetAttrString(pmodule, const_cast<char *>(function));
    Py_DECREF(pmodule);
    if (!pfunction)
    {
        PyObject *type = PyErr_Occurred();
        if (type == PyExc_AttributeError)
        {
            PyErr_Clear();
            return 0;
        }

        PyError("PyModuleRunFunction");
        return -2;
    }

    if (pfunction == Py_None)
    {
        return 0;
    }

    va_list args_list;
    va_start(args_list, args_format);
    args = Py_VaBuildValue(const_cast<char *>(args_format), args_list);
    va_end(args_list);

    if (!args)
    {
        Py_DECREF(pfunction);
        return -3;
    }

    presult = PyObject_CallObject(pfunction, args);
    if (presult == 0)
    {
        PyError("PyModuleRunFunction");
        Py_XDECREF(pfunction);
        Py_XDECREF(args);
        return -1;
    }

    Py_XDECREF(pfunction);
    Py_XDECREF(args);

    return ConvertResult(presult, result_format, result);
}

 

  Py_InitModule3 is used to define a python module. The first parameter is the module name, the second parameter is the method description set in the module, and the third parameter is the module description information. In the above code, we define a module called pycallc, which describes the collection module_methods describes two methods py_set_data and py_get_data. The function addresses corresponding to these two methods are PySetData and PyGetData. These two functions will eventually call SetData and GetData defined above respectively. In this way, we use the PY of the pycallc module in the python script_ set_ Data and PY_ get_ The data method can set and obtain data. Looking at the above implementation, in fact, the main function of this Python module is to encapsulate the functions defined in c again, and the encapsulated functions can be recognized by python.

 

Calling the python module implemented in c in Python script

Since a python module pycallc has been initialized through c code, we can import this module through import and call the functions in this module in the script. The specific codes are as follows:

1 # -*- coding: utf-8 -*-
2 
3 import pycallc
4 
5 def test():
6     print 'in python : ', pycallc.py_get_data()
7     pycallc.py_set_data("change hello world!")

In this way, we implement the method of calling c in python script.

Link to the complete code demo above: https://github.com/morningstatus/python/tree/master/ccallpy

 

summary

Calling python from c above and calling c from python are actually fixed steps that will be used when you know it. There is no question of whether you will, only the question of whether you want to know. You may think this technology is very advanced before you contact it, but in fact, it is not so difficult as long as you spend a little effort to understand it. ***

 

Added by deejay on Tue, 04 Jan 2022 11:05:06 +0200