Python 3 calls and encapsulates and calls c program

Python 3 calls and encapsulates and calls c program

First, let's look at an example:
Import c program implementation:

import time
from ctypes import *

def main():
    num = int(input("Please enter an integer value:"))
    result = 0
    start_time = time.time()
    result = cdll.LoadLibrary("./add.so")
    result.my_add(num)

    end_time = time.time()
    print("Total time%s"%(end_time-start_time))

if __name__ == "__main__":
    main()

Pure python implementation

import time
  
def main():
    num = int(input("Please enter an integer value:"))
    result = 0
    start_time = time.time()

    for i in range(num+1):
        result += i
    print("From 1 to%d The cumulative calculation result is%d"%(num,result))
    end_time = time.time()
    print("Total time%s"%(end_time-start_time))

if __name__ == "__main__":
    main()

Comparison of execution results

[root@bogon test1]# python3 c_add.py
 Please enter an integer value:200
 The cumulative calculation result from 1 to 200 is 20100
 Total time 0.00023293495178222656
[root@bogon test1]# python3 python_add.py
 Please enter an integer value:200
 The cumulative calculation result from 1 to 200 is 20100
 Total time 7.748603820800781e-05
[root@bogon test1]# vim c_add.py
[root@bogon test1]# vim python_add.py

You can clearly see the comparison results of c operation time and python operation time.
c comparison with python: python is not good at "massive computation" tasks. The advantage of python program is that it is easy to write and suitable for "IO intensive jobs" (such as opening files, downloading pictures and running scripts). The way python can quickly realize "computing intensive operation" is to "take the c code and use it directly".

1, Python 3 calls c program directly

The first code above is an example of Python 3 calling c program directly. The steps are divided into four steps. Let's implement it together:
Four steps:
1. Place the c suffix files are compiled into dynamic library files (. so end)

gcc original file name.c -shared -o New file name.so
 perhaps
gcc original file name.c  -shared -o test.so -I/usr/include/python3.6m -fPIC -lpython3

Examples
 To be test.c Compile as test.so take as an example
gcc test.c -shared -o test.so

2. Import header file in python file

from ctypes import *

3. Introduce c dynamic library into python and receive the reference of dynamic library with variable

Format:
Variable name = cdll.LoadLibrary("Dynamic library file path")

Example:
result = cdll.LoadLibrary("./add.so")

4. Call dynamic library method

Format:
Dynamic library reference.Library function(parameter)

Example:
result.my_add(num)

Implementation example:
1. Prepare c program add c

#include <stdio.h>
  
void my_add(int num) {
    long int result = 0;
    for(long int i = 1; i <= num; i++) {
        result += i;
    }

    printf("From 1 to%d The cumulative calculation result is%ld\n",num,result);
}

Compile into so library file:

gcc add.c -shared -o add.so

2. Python 3 code implementation:

import time
#introduce
from ctypes import *

def main():
    num = int(input("Please enter an integer value:"))
    result = 0
    start_time = time.time()
    #Import library files directly
    result = cdll.LoadLibrary("./add.so")
    #Call method
    result.my_add(num)

    end_time = time.time()
    print("Total time%s"%(end_time-start_time))

if __name__ == "__main__":
    main()

Python3 execution_ add. py

[root@bogon test1]# python3 c_add.py
 Please enter an integer value:200
 The cumulative calculation result from 1 to 200 is 20100
 Total time 0.00023293495178222656

2, c program is called in the form of module after Python 3 encapsulation

Let's take a small demo as an example. Here we first show the demo directory structure

demo
  -- install.sh # sh build file
  -- main.py    # Test file
  -- setup.py # Build py extension library file
  -- add.c   # C extension library

install.sh

python3 setup.py install

rm -rf ./dist
rm -rf ./build

setup.py
Encapsulate startup file

from distutils.core import setup, Extension

setup(name='aaa', # Defined module name
      version='1.0',
      ext_modules=[
          Extension('aaa', ['./add.c']) # aaa is the module name defined in the c file, add c is the c file path
      ]
     )

test.c
Simple fib function encapsulation. The following is the encapsulation method of python3, which can be used by python2

#include <Python.h>

//a func to calc fib numbers
int cFib(int n)
{
    if (n<2) return n;
    return cFib(n-1) + cFib(n-2);
}

// Bridge the return value of c and py parameters
static PyObject* fib(PyObject* self,PyObject* args)
{
    int n;
    if (!PyArg_ParseTuple(args,"i",&n))
        return NULL;
    return Py_BuildValue("i",cFib(n));
}

// Define the functions / functions contained in the module
static PyMethodDef module_methods[] = {
    {"fib",(PyCFunction) fib, METH_VARARGS,"calculates the fibonachi number"},
    {NULL,NULL,0,NULL}
};

// Encapsulate a module structure
static struct PyModuleDef aaa =
{
    PyModuleDef_HEAD_INIT,
    "aaa", /* name of module */
    "",          /* module documentation, may be NULL */
    -1,          /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    module_methods
};

// init this module is a py module
PyMODINIT_FUNC PyInit_aaa(void)
{
    return PyModule_Create(&aaa);
}

main.py
Used to test whether the c extension library is built successfully

import aaa

if __name__ == '__main__':

    for num in range(10):
        print(aaa.fib(num))

It should be noted that the module name you expect to generate must be consistent with several key names in the c file, in PyModuleDef structure and setup

After the above files are ready, enter the directory for testing
Execute build sh file

[root@bogon test2]# ./install.sh 
running install
running build
running build_ext
building 'aaa' extension
creating build
creating build/temp.linux-loongarch64-3.6
loongarch64-loongson-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -g -D_GNU_SOURCE -fPIC -fwrapv -O2 -g -D_GNU_SOURCE -fPIC -fwrapv -O2 -g -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python3.6m -c ./add.c -o build/temp.linux-loongarch64-3.6/./add.o
creating build/lib.linux-loongarch64-3.6
loongarch64-loongson-linux-gnu-gcc -pthread -shared -Wl,-z,relro -Wl,-z,now -g -Wl,-z,relro -Wl,-z,now -g build/temp.linux-loongarch64-3.6/./add.o -L/usr/lib64 -lpython3.6m -o build/lib.linux-loongarch64-3.6/aaa.cpython-36m-loongarch64-linux-gnu.so
running install_lib
copying build/lib.linux-loongarch64-3.6/aaa.cpython-36m-loongarch64-linux-gnu.so -> /usr/local/lib64/python3.6/site-packages
running install_egg_info
Removing /usr/local/lib64/python3.6/site-packages/aaa-1.0-py3.6.egg-info
Writing /usr/local/lib64/python3.6/site-packages/aaa-1.0-py3.6.egg-info

If no error is reported, the construction is successful

Test:

[root@bogon test2]# python3 main.py 
0
1
1
2
3
5
8
13
21
34

If the problem of importing the module is prompted when executing the test script, for example:
ImportError: The dynamic module does not define the init function
Please check that the module name expected to be generated must be consistent with several key names in the c file, i.e. setup. In the above example Py and test All aaa places in c

Encapsulation in the case of two c and header files
C program test_add.c

#include "test.h"
  
int add(int a,int b)

{
    return a+b;

}

Header file test h

int add(int a,int b);

C extension program test_add_py.c. Only for python3

#include <Python.h>
#include "test.h"

PyObject* wrap_add(PyObject* self, PyObject* args)
{
        int n0,n1, result;
        if (!PyArg_ParseTuple(args, "ii", &n0, &n1))
           return NULL;
        printf("n0 = %d\n",n0);
        printf("n1 = %d\n",n1);
        result = add(n0,n1);

        return Py_BuildValue("i", result);
}

static PyMethodDef testMethods[] =
{
  {"add", wrap_add, METH_VARARGS, "Add"},
  {NULL, NULL}
};

static struct PyModuleDef test = {
        PyModuleDef_HEAD_INIT,
        "test",
        NULL,
        -1,
        testMethods};

PyMODINIT_FUNC PyInit_test(void)
{
        return PyModule_Create(&test);
}             

compile

 gcc -fPIC -shared -o test.so -I/usr/include/python3.6m test_add.c  test_add_py.c -lpython3

Test main py

import test

if __name__ == '__main__':
    print(test.add(2,4))

implement

[root@bogon test2]# python3 main.py 
n0 = 2
n1 = 4
6

Reference #include < python h> Python3 devel needs to be installed

Keywords: Python C

Added by cainscripter on Mon, 14 Feb 2022 11:07:49 +0200