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