Python example three-to-one call between Python and C/C + +

Source: Internet
Author: User
Tags python script

first, the question

the python module and the dynamic inter-Library call between C/+ + will be involved in the actual application, here is a summary.

second, Python calls C + +1. Python calls c dynamic link library

Python calls the C library relatively simple, packaged into so without any encapsulation, and then using Python's ctypes call.
(1) C language file: PYCALL.C

/***gcc-o libpycall.so-shared-fpic pycall.c*/#include <stdio.h> #include <stdlib.h>int foo (int a, int b) {
   printf ("You input%d and%d\n", A, b);  return a+b;}
(2) GCC compilation generates dynamic library Libpycall.so:gcc-o libpycall.so-shared-fpic pycall.c. When using g++ to compile a function or method in the code that generates a C dynamic library, you need to use extern "C" to compile.
(3) Python calls the file of the dynamic library: pycall.py
Import Ctypesll = Ctypes.cdll.LoadLibrary lib = ll ("./libpycall.so")  Lib.foo (1, 3) print ' ***finish*** '
(4) Operation result:

2. Python calls C + + (Class) dynamic link library
extern "C" is required to assist, that is, you can only call the C function, you cannot call the method directly, but you can parse the C + + method. Instead of using extern "C", the built-in dynamic-link library does not have a symbol table for these functions.
(1) C + + class file: Pycallclass.cpp
#include <iostream>using namespace Std;class testlib{public    :        void Display ();        void display (int a);}; void TestLib::d isplay () {    cout<< "first display" <<ENDL;} void TestLib::d isplay (int a) {    cout<< "Second display:" <<A<<ENDL;} extern "C" {    TestLib obj;    void display () {        obj.display ();       }    void Display_int () {        obj.display (2);       }}
(2) g++ compilation generates dynamic library libpycall.so:g++-O libpycallclass.so-shared-fpic pycallclass.cpp.
(3) Python calls the file of the dynamic library: pycallclass.py
Import Ctypesso = Ctypes.cdll.LoadLibrary lib = so ("./libpycallclass.so") print ' Display () ' Lib.display () print ' Display ( (+) ' Lib.display_int (100)
(4) Operation result:

3. Python calls the C + + executable program(1) C + + program: main.cpp
#include <iostream>using namespace Std;int Test () {    int a = ten, B = 5;    return a+b;} int main () {    cout<< "---begin---" <<endl;    int num = Test ();    cout<< "num=" <<num<<endl;    cout<< "---end---" <<ENDL;}
(2) compiled into binary executable file: g++-o testmain main.cpp.
(3)python calling program: main.py
Import Commandsimport Osmain = "./testmain" if os.path.exists (main):    rc, out = Commands.getstatusoutput (main)    print ' rc =%d, \nout =%s '% (RC, out) print ' * ' *10f = Os.popen (main)  data = F.readlines ()  f.close ()  Print dat Aprint ' * ' *10os.system (main)
(4) Operation result:

4. Extend Python (C + + writes extensions for Python )       all code that can be integrated or imported into other Python scripts can be called extensions. You can use Python to write extensions, or you can write extensions in a compiled language such as C and C + +. At the beginning of the design, Python took into account the need to make the module's import mechanism abstract enough. Abstraction to the code that uses the module does not understand the specifics of the implementation of the module. python has the advantage that it is convenient to add new features to the language, be customizable, and code can be reused.
       Creating an extension for Python requires three main steps: Creating application code, using templates to wrap code, and compiling and testing.
(1) Create application code
 #include <stdio.h> #include <stdlib.h> #include <string.h>int fac (int n) {if (n < 2) return (1);/* 0! = = 1! = = 1 */return (n) *fac (n-1); /* n! = = N (n-1)! */}char *reverse (char *s) {Register char T,/* TMP */*p = s,/* fwd */*q = (s + (strlen (s)-1));         /* BWD */while (P < q)/* If p < Q */{t = *p;        /* Swap & Move Ptrs */*p++ = *q;    *q--= t; } return (s);}    int main () {char s[bufsiz]; printf ("4!    = =%d\n ", FAC (4)); printf ("8!    = =%d\n ", FAC (8)); printf ("12!    = =%d\n ", FAC (12));    strcpy (S, "abcdef");    printf ("Reversing ' abcdef ', we get '%s ' \ n", reverse (s));    strcpy (S, "Madam");    printf ("Reversing ' madam ', we get '%s ' \ n", reverse (s)); return 0;} 
There are two functions in the code above, one is the function FAC () that recursively seeks factorial, and the other reverse () function implements a simple string inversion algorithm whose main purpose is to modify the incoming string so that its contents are completely inverted, but do not need to request memory to reverse the copy method.
(2) Use a template to package the code
The code for the interface is called the "boilerplate" code, which isApplicationAn essential part of the interaction between the code and the Python interpreter. The sample is divided into 4 steps: A, a Python header file, B, a wrapper function for each function of each module, such as pyobject* Module_func (), C, add a type for each module such as Pymethoddef modulemethods[] An array of D, add module initialization function void Initmodule ().
#include <stdio.h> #include <stdlib.h> #include <string.h>int fac (int n) {if (n < 2) return (1); Return (n) *fac (n-1);}    Char *reverse (char *s) {Register char T, *p = s, *q = (s + (strlen (s)-1));        while (S && (P < q)) {t = *p;        *p++ = *q;    *q--= t; } return (s);}    int Test () {char s[bufsiz]; printf ("4!    = =%d\n ", FAC (4)); printf ("8!    = =%d\n ", FAC (8)); printf ("12!    = =%d\n ", FAC (12));    strcpy (S, "abcdef");    printf ("Reversing ' abcdef ', we get '%s ' \ n", reverse (s));    strcpy (S, "Madam");    printf ("Reversing ' madam ', we get '%s ' \ n", reverse (s)); return 0;}    #include "Python.h" Static Pyobject *extest_fac (Pyobject *self, Pyobject *args) {int num; if (!    Pyarg_parsetuple (args, "I", &num)) return NULL; Return (pyobject*) py_buildvalue ("I", FAC (num));}    Static Pyobject *extest_doppel (Pyobject *self, Pyobject *args) {char *orig_str;    Char *dupe_str; Pyobject* retval; if (!    Pyarg_parsetuple (args, "s", &orig_str)) return NULL;    retval = (pyobject*) py_buildvalue ("ss", Orig_str, Dupe_str=reverse (StrDup (ORIG_STR))); Free (DUPE_STR);             #防止内存泄漏 return retval;}    Static Pyobject *extest_test (Pyobject *self, Pyobject *args) {test (); Return (pyobject*) Py_buildvalue ("");}     Static pymethoddefextestmethods[] ={{"FAC", EXTEST_FAC, Meth_varargs}, {"Doppel", Extest_doppel, Meth_varargs}, {"Test", Extest_test, Meth_varargs}, {null, NULL},};void initextest () {py_initmodule ("Extest", Extestmethods );}
Python.h header files in most Unix-like systems in the/usr/local/include/python2.x or/usr/include/python2.x directories, the system generally knows the path to file installation.
Add the wrapper function, where the module name is Extest, then create a wrapper function called EXTEST_FAC (), in the Python script is the first import Extest, and then call EXTEST.FAC (), whenEXTEST.FAC () is called when the wrapper functionEXTEST_FAC () is called and the wrapper function acceptsA python integer parameter, convert it to a C integer, then call the FAC () function of C, get an integer return value, and finally return the integer number of the return value to Python as the result of the entire function call. The other two wrapper functions Extest_doppel () and extest_test () are similar.
Conversion from Python to C with the Pyarg_parse* series function,int pyarg_parsetuple (): Transfer the parameters from Python to C;int pyarg_parsetupleandkeywords () to the same as Pyarg_parsetuple (), but also parse the keyword parameters. ; theythe use of C is similar to the SSCANF function, all accept a string stream, and according to a specified format string to parse, the result is placed in the corresponding pointer to the variable, their return value of 1 means that the resolution is successful, the return value of 0 indicates failure。the conversion function from C to python is pyobject* py_buildvalue (): converts the data of C into a Python object or a set of objects, and then returns it ;The use of Py_buildvalue is similar to sprintf, which converts all parameters into a Python object in the format specified by the format string.
Conversion code for data conversion between C and Python:

Add an array of type Pymethoddef modulemethods[] for each module so that the Python interpreter can import and invoke them, each containing the name of the function in Python, the name of the corresponding wrapper function, and a meth_ VARARGS constant, Meth_varargs indicates that the parameter is passed in as a tuple. If you need to usePyarg_parsetupleandkeywords () function to parse a named parameter, you also need to make the symbolic constant and the meth_keywords constant logical and operational constants. The array ends with two null to represent the end of the function information list .
The final part of all work is the initialization function of the module, calling the Py_initmodule () function, and passing in the name of the module name and modulemethods[] array so that the interpreter can correctly invoke the function in the module.
(3) Compiling
In order for the new Python extensions to be created, they need to be compiled with the Python library, and the Distutils package is used to compile, install, and distribute the modules, extensions, and packages.
To create a setup.py file, the most important work for compiling is done by the setup () function:
#!/usr/bin/env pythonfrom distutils.core Import setup, Extensionmod = ' Extest ' Setup (Name=mod, Ext_modules=[extension ( MOD, sources=[' extest2.c ')])
Extension () The first parameter is the name of the (full) extension, and if the module is part of the package, add '. ' The name of the complete package that separates. The above extension is independent, so the name just writes "Extest" on the line; The sources parameter is a list of all source code files, with only one file extest2.c. Setup requires two parameters: one name parameter indicates which content to compile, and the other list parameter lists the object to compile, and the above is compiled with an extension, so the value of the Ext_modules parameter is set to the list of extension modules.
Run the setup.py build command to start compiling our extensions, prompting for some information:
Creating Build/lib.linux-x86_64-2.6gcc-pthread-shared build/temp.linux-x86_64-2.6/extest2.o-l/usr/lib64- Lpython2.6-o build/lib.linux-x86_64-2.6/extest.so
(4) Import and test
Your extension will be created in the build/lib.* directory under the directory where the setup.py script is run, you can switch to that directory to test the module, or you can install it in Python with a command: Python setup.py install, which prompts for the message.
Test module:


(5) Reference counting and thread safety
Python object reference count macro: Py_incref (obj) increases the reference count of the object obj, and py_decref (obj) reduces the reference count of the object obj. Py_incref () and Py_decref () Two functions also have a version that checks if the object is empty first, py_xincref () and Py_xdecref () respectively.
Programmers who compile extensions must be aware that the code is likely to be run in a multithreaded Python environment. These threads use two C macros py_begin_allow_threads and Py_end_allow_threads,by isolating code and Threads, which guarantees both runtime and non-runtime security, the code that is wrapped by these macros will allow other threads to run.

Third, C + + call Python

C + + can invoke the Python script, then you can write some Python script interface for C + + calls, at least can be used as a text of Python dynamic link library,
You can change it when you need it, as long as you don't change the interface. The disadvantage is that C + + program once compiled, and then change it is not so convenient.
(1) Python script: pytest.py

#test functiondef Add (b):    print "In Python function add"    print "a =" + str (a)    print "b =" + str (b)    pri  NT "ret =" + str (a+b)    returndef foo (a):    print "in Python function foo"    print "a =" + str (a)    print "ret = + STR (A * a)    return class guestlist:    def __init__ (self):        print "AAAA"    def P ():  print "BBBBB" 
   def __getitem__ (self, id):  return "CCCCC" def update ():    guest = guestlist ()    print guest[' AA '] #update ()
(2) C + + code:
/**g++-o callpy callpy.cpp-i/usr/include/python2.6-l/usr/lib64/python2.6/config-lpython2.6**/#include < Python.h>int Main (int argc, char** argv) {//Initialize Python//before using a Python system, you must initialize IT//with py_initialize. It will load the Python built-in module and add the system path//path to the module search path.    This function does not return a value, it is necessary to check whether the system//is initialized successfully using py_isinitialized.    Py_initialize (); Check if initialization succeeds if (!    Py_isinitialized ()) {return-1; }//Add the current path//run the input string directly as Python code, return 0//To indicate success, 1 for error.    Most of the time the error is due to a syntax error in the string//.    pyrun_simplestring ("Import sys");     Pyrun_simplestring ("print '---import sys---'");    Pyrun_simplestring ("Sys.path.append ('./')");    Pyobject *pname,*pmodule,*pdict,*pfunc,*pargs;    Load the script named Pytest pName = pystring_fromstring ("Pytest");    Pmodule = Pyimport_import (pName);        if (!pmodule) {printf ("can ' t find pytest.py");        GetChar ();    return-1;    } pdict = Pymodule_getdict (pmodule);    if (!pdict) {return-1; }//Find the function called Add printf ("----------------------\ n ");    PFunc = pydict_getitemstring (pdict, "add"); if (!pfunc | |!)        Pycallable_check (PFunc)) {printf ("can ' t find function [Add]");        GetChar ();     return-1;    }//Parameter into the stack *pargs;    PArgs = Pytuple_new (2);    pyobject* Py_buildvalue (char *format, ...) Convert C + + variables into a Python object. This function is used when you need to pass variables from//C + + to Python. This function//is somewhat similar to C's printf, but in a different format.    Common formats are//s for strings,//I for integer variables,//F for floating-point numbers,//O for a Python object.    Pytuple_setitem (PArgs, 0, Py_buildvalue ("L", 3));    Pytuple_setitem (PArgs, 1, Py_buildvalue ("L", 4));    Call the Python function pyobject_callobject (PFunc, PArgs);    The following paragraph is to find the function foo and execute foo printf ("----------------------\ n");    PFunc = pydict_getitemstring (pdict, "foo"); if (!pfunc | |!)        Pycallable_check (PFunc)) {printf ("can ' t find function [foo]");        GetChar ();     return-1;    } PArgs = Pytuple_new (1);     Pytuple_setitem (PArgs, 0, Py_buildvalue ("L", 2));         Pyobject_callobject (PFunc, PArgs); printf ("----------------------\ n ");    PFunc = pydict_getitemstring (pdict, "Update"); if (!pfunc | |!)        Pycallable_check (PFunc)) {printf ("can ' t find function [UPDATE]");        GetChar ();     return-1;    } PArgs = pytuple_new (0);    Pytuple_setitem (PArgs, 0, Py_buildvalue (""));         Pyobject_callobject (PFunc, PArgs);    Py_decref (PName);    Py_decref (PArgs);    Py_decref (Pmodule);    Close Python py_finalize ();  return 0;}
(3) C + + compiled into binary executable: g++-o callpy callpy.cpp-i/usr/include/python2.6-l/usr/lib64/python2.6/config- lpython2.6, the compile option requires you to manually specify Python's include path and link path (Python version number is based on the specific case).
(4) Operation result:

Iv. Summary(1) The mutual invocation of Python and C + + is just the test code, and the specific project development has to refer to the Python API documentation.
(2) The interaction between the two, C + + can write extension modules for Python, Python can also provide a scripting interface for C + +, more convenient for practical applications.
(3) If there is insufficient, please leave a message, thank you first!

Python example three-to-one call between Python and C/C + +

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.