The interaction programming between Python and C + +

Source: Internet
Author: User
Tags class definition documentation garbage collection wrapper
Basic knowledge


Compiling languages and interpreting languages


Although many programming techniques are now blending, there are many interpretive languages with compiled systems, and compiled languages with complex run-time systems, but usually we can distinguish them quite clearly. In this context, Python and C + + are among the more extreme representatives of the two types of technology.
Compile-time and run-time


The power of C + + is the efficient generation of products and powerful and complex compilation systems. With the syntax of C + +, you can generate very flexible and powerful programs, most of which are done in the process of compiling a program. In contrast, C + + does not have a standard runtime (the CLI system has not really become a C + + standard, can only say that a C + + on the CLI system to run the standard), to establish a perfect runtime, either put a lot of cost, or find a suitable run-time environment call. Python itself is a mature and complete scripting language, with open programming and extension interfaces, and its own object mechanism design is very suitable for external invocation, Python and the compiler language, especially C/s, the mutual embedding is increasingly becoming the focus of attention.
Mutual embedding


Python has a variety of implementations, the more famous is the official implementation of the C language, Java version of the jython,.net version of the IronPython, it is worth mentioning that the latter both were developed by Jim Hugunin, who now hosts the Dynamic Language research project. In addition, there is a CPython call to the. NET bridging system Pythondotnet, developed by a technical person from the Zope community. The most widely used embedded situation now is the mutual embedding between C + + and CPython.
The official version of Python itself is written in C and has an open C interface. Using the C language to invoke and extend Python is very simple. Based on this premise, it is not complicated to interoperate with Python using the C + + language. There are already a number of C + + libraries for Python API encapsulation, and here we're going to talk about Boost.python. This is one of the important components of the famous C + + library boost.
Extending Python with C + +


Getting Started with Python extensions


Python allows you to invoke language and operating system-independent dynamic-link libraries under certain rules. Typically,. dll under Windows and the. so file under *nix. The difference between the operating system is masked by C + + compilers, boost libraries, and the Python interpreter, and ultimately programmers can ignore the differences.
When embedding, consider Python run-time restrictions, python virtual machines can only operate Python objects, and the virtual machine has its own memory management mode, should be based on the situation of C + + programs and the Python environment for the exchange of information to carry out the necessary encapsulation and unpacking.
Python itself provides the interface files required for the C language extension, and can find the corresponding files in the Python include,libs,dlls directory.
A pure C-language Python extension might resemble the following:
#include <Python.h>


Static Pyobject *
Spam_system (Pyobject *self, Pyobject *args)
{
const char *command;
int STS;


if (! Pyarg_parsetuple (args, "s", &command))
return NULL;
STS = System (command);
Return Py_buildvalue ("I", STS);
}




We encapsulate the above functions into a dynamic link library based on the specific operating system and development tools, and put them in the Python dynamic link library search path (DLLs in Python for Windows). You can use it as a module in Python.


C + + Encapsulation


We know that C + + code encapsulation mechanism and C are different, compared to the real pure C language, C + + more complex. For example, it has a virtual function, a template, which makes the runtime more complex and flexible, which enables some syntax derivations that are more complex than macros to be implemented. Boost.python's encapsulation capability for C + + programs is based on template. What we're going to do is turn the functions, classes, data members, and so on in the C + + program into Python objects.
BOOST. Python encapsulates the Python dynamic link library interface for each platform, all we have to do is call it, encapsulate the definition that needs to be exposed, and then instruct the compiler to generate a dynamic link library.
function encapsulation


Python APIs use callback functions to invoke Python objects and functions. Boost provides a complete function encapsulation process, a simple encapsulation process as follows:


Hello World


Following C/s + + tradition, let's start with the "Hello, World". A C + + Function:


Char const* greet ()
{
Return to "Hello, world";
}
Can is exposed to Python by writing a Boost.python wrapper:


#include <boost/python.hpp>
Using namespace boost::p Ython;


Boost_python_module (Hello)
{
def ("greet", greet);
}
That ' s it. We ' re done. We can now build this as a shared library. The resulting DLL is now visible to Python. Here's a sample Python session:


>>> Import Hello
>>> Print Hello.greet ()
Hello, world




Above from boost documentation.
Object-oriented


Object management, reference counting
Python virtual machines provide reference counting and automatic garbage collection capabilities, but C + + objects do not have the capability (C + + objects run outside of the Python virtual machine). To avoid memory usage during program operation, you need to provide reference count management for the pointers passed in the function, and boost uses the "invoke protocol" to support this feature, see boost documentation, "Call Policies."
Encapsulation of C + + objects to Python objects
The boost documentation provides a way to encapsulate C + + objects into Python objects by parsing the C + + class definition into a form that conforms to the C API in the Class_ template, a shape like this:


struct WORLD
{
void set (std::string msg) {this->msg = msg;}
std::string greet () {return msg;}
std::string msg;
};
C + + code can be encapsulated in the following ways:


#include <boost/python.hpp>
Using namespace boost::p Ython;


Boost_python_module (Hello)
{
Class_<world> ("World")
. def ("greet", &world::greet)
. DEF ("set", &world::set)
;
}
The key point here is the def of the Boost_python_module macros and class<> templates that encapsulate the code. To support the rich content of C + + classes, Boost.python provides a number of calling methods, which are more common and more important than the support of constructors, overloads, and virtual functions.
The encapsulation of a constructor is encapsulated by the __init__ template, and different constructor overloads can be differentiated and encapsulated by a parameter list. An example of this is given in the boost documentation:
Class_<world> ("World", Init<std::string> ())
. def (Init<double, double> ())
. def ("greet", &world::greet)
. DEF ("set", &world::set)
;
Support for common function overloading is actually a function encapsulation method, and it has nothing to do with whether the function is a member of a class. The basic idea is to define different function forms as different function pointers, and then encapsulate them in the form of ordinary functions.
The support of virtual functions is more complex, and boost supports it through multiple inheritance, and users need to define a wrapper for a base class with multiple inheritance, and then expose the encapsulated class. When reading the boost document, be aware of the code that encapsulates the class when it exposes the interface with Class_, and here is an example of the boost documentation:
struct Basewrap:base, wrapper<base>
{
int F ()
{
if (override F = This->get_override ("f"))
return f (); *note*
return Base::f ();
}


int Default_f () {return this->base::f ();}
};


Class_<basewrap, boost::noncopyable> ("Base")
. def ("F", &base::f, &basewrap::d efault_f)
;
Note that the Class_ template parameters in the encapsulated code are basewrap, but the second function in Def is &base::f. The third function of DEF provides some information about the function encapsulation, which indicates the default implementation of the virtual function. Please refer to the Boost documentation for more usage. More complex features are also available in boost, such as the ability to define the properties of a Python class (which is even simpler than in Python).
Embed Python in C + + programs


Reference interpreter


The Python standard external invocation method is not complex and can be found in Python documentation. The simplest way to invoke it is as follows:


#include <Python.h>


Int
Main (int argc, char *argv[])
{
Py_initialize ();
Pyrun_simplestring ("From time import time,ctime\n")
' Print ' Today is ', CTime (Time ()) \ n ");
Py_finalize ();
return 0;
}
Py_initialize (); Start the virtual machine, py_finalize (), terminate it. Pyrun_simplestring is used to execute statements. Boost continues this way and focuses on getting the interaction process simpler. The simplest example in the Boost program is as follows:




Py_initialize ();
Object Main_module (
Handle<> (Borrowed (Pyimport_addmodule ("__main__"))));


Object main_namespace = main_module.attr ("__dict__");


Handle<> Ignored (pyrun_string (


"Hello = File (' Hello.txt ', ' W ') \ n"
"Hello.write (' Hello world! ') \ n "
"Hello.close ()"


, Py_file_input
, Main_namespace.ptr ()
, Main_namespace.ptr ())
));
Py_finalize ();
From this complexity of the program, it does not show the advantages of boost, it is even more complex than the C program. But here you can learn the basic framework. Perhaps the following more complex example can illustrate some of the problems:


Object Main_module (
Handle<> (Borrowed (Pyimport_addmodule ("__main__"))));


Object main_namespace = main_module.attr ("__dict__");


Handle<> Ignored (pyrun_string (


"Result = 5 * * 2"


, Py_file_input
, Main_namespace.ptr ()
, Main_namespace.ptr ())
));


int five_squared = extract<int> (main_namespace["result"));
Here are some of the benefits of boost, such as capturing Python data through C + + objects (here Main_namespace objects) and translating them into C + + data (extract templates). The following example shows the C + + exception protection provided by boost for the Python environment:
Try
{
Object Result (handle<> (pyrun_string (
"5/0"
, Py_eval_input
, Main_namespace.ptr ()
, Main_namespace.ptr ()))
));


Execution'll never get here:
int Five_divided_by_zero = extract<int> (result);
}
catch (Error_already_set)
{
Handle the exception in some way
}
Of course, we can also choose an exception-free version:


handle<> result (Allow_null (pyrun_string (
"5/0"
, Py_eval_input
, Main_namespace.ptr ()
, Main_namespace.ptr ())));


if (!result)
Python exception occurred
Else
Everything went okay, it ' s safe to use the result
Calling script




Pyrunstring is Python's C-api,python provides a series of invocation methods for program execution script use, also includes the Pyrun_file such direct call file function, of course, it does not support C + + I/O, using C-style file pointers.





PostScript


Finally, using boost, whether you want to expand or embed Python, you need to precompile the boost library, which is also described in Boost's documentation. When using boost, the precompiled Lib is linked to the link sequence, and the DLL is placed where the application can access it.

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.