Exposing C to Python

[ LiB ]

Exposing C++ to Python

As I'm sure you saw with all the examples in this chapter, it's very easy to call Python from C++. It's another thing altogether to expose C++ to Python, however.

Usually, when a programmer wants to expose something to Python from C++, he builds a DLL or SO file that holds the C/C++ code, and then calls it from Python. You can find hundreds of tutorials that describe how to do this.

It is rare, however, to find information on exposing C++ to Python, while at the same time, embedding the Python interpreter into the program. So, here I come, to the rescue.

Trials and Tribulations

There are many ways you can expose C++ to Python. When I first started working on this idea, I had heard about the C++ Boost library (http://www.boost.org), which has a module named boost::python. This is an excellent library, even though it is still under construction.

I spent weeks integrating boost::python into the BetterMUD, making a really stable design that worked perfectly . And then one day I decided to check to make sure it worked in VC6.

It doesn't. I slammed my head on the table a few times over this, believe me. Boost::python uses templates heavily , and since VC6 has very awkward and incomplete template support, getting boost::python to work in VC6 proved to be ultimately impossible . I ended up scrapping the entire design, and I had to go back to square one!

Using boost::python on a real compiler actually works like a breeze . If you use VC7 or GCC, I urge you to look into boost. It's really cool.

NOTE

If there's a moral to learn in this story, it's that VC6 is an evil, horrible, ancient compiler, and you should upgrade to VC7 or the latest version GCC this very instant! GO GO GO!

Here, Take a SWIG

When I ultimately had to give up on boost, I had to find a replacement quickly. Luckily, the SWIG library (available free at http://www.swig.org, and you can find it on the CD as well, in / goodies /Libraries/SWIG) is easy to use.

Just install it and add your SWIG directory to your system's path environment variable (for example, in Windows I had to add D:\Programming\SWIG-1.3.19\ to my PATH environment variable, by going to Start->Settings->Control Panel->System->Advanced->Environment Variables).

Demo 17.3SWIGging It Down

To show you how simple SWIG is, I've created a simple Demo for you, Demo 17.3.

C++ Header

First, create a header containing the code Python is to call. I've put all this code inside SWIGME.h:

 std::string SWIGFunction() {     return "This has been brought to you by the letter C"; } class SWIGClass { public:     SWIGClass( int value ) : m_value( value ) {}     void PrintValue()  { std::cout << "My Value is " << m_value << std::endl; } protected:     int m_value; }; 

I've created a simple function that returns a string, and a simple class that holds and prints an integer value.

SWIG Interface

Now I need to create a SWIG interface file, which I call SWIG.i. Interface files are a simple format that SWIG uses to figure out what you want to call from Python:

 /* File : SWIGME.i */ %module SWIGME %include "std_string.i" /* grab the original header file here */ %include "SWIGME.h" 

The first part of the file declares that you want to create a Python module named SWIGME .

By default SWIG doesn't support std::string (since SWIG was originally a C tool, it really only supports evil char* s), but recent versions of the library come with a file called std_string.i, which makes SWIG use std::string s properly. Cool!

The final part of the code takes the contents of the SWIGME.h file and includes them into the interface file.

Generating SWIGME

Now that you have a header and interface file, you can generate C++/Python code with SWIG. Open up a console window, go into the Demo 17.3 directory, and type this:

 swig -c++ -python SWIGME.i 

Since you're going to be generating C++ code, you must use the -c++ flag, so that SWIG recognizes classes properly. The -python flag means you're going to be interfacing the code with Python, and of course you need to tell it about the interface file too.

Now that you've run the program, it should have generated two files for you: SWIGME.py, and SWIGME_wrap.cxx.

The first file is a Python module that allows Python to know about your C++ code, and the second is a C++ module that contains all the wrapper code for talking with Python.

NOTE

SWIG isn't just a Python tool. You can use SWIG to interface C/C++ with a whole bunch of languages: TCL, Python, Perl, Guile, Java, Ruby, Mzscheme, PHP, Oclaml, C#, Chicken Scheme, and some others. It's a cool utility.

Python Tester

Now I want to create a Python module that calls the C++ functions. I've put this into a file named swiggy.py :

 import SWIGME s = SWIGME.SWIGFunction() print "Result of SWIGME.SWIGFunction: " + s print "Creating SWIGME.SWIGClass of 10:" a = SWIGME.SWIGClass( 10 ) a.PrintValue() print "Creating SWIGME.SWIGClass of 42:" b = SWIGME.SWIGClass( 42 ) b.PrintValue() 

This simply calls the C++ functions and classes as if they were Python functions and classes. It should be executed the moment the module is loaded.

C++ Test Frame

The final step is to create the C++ test frame that will import the SWIG-generated Python-C++ module, and run module swiggy . This is file Demo17-03.cpp:

 #include "SWIGME.h" #include "SWIGME_wrap.cxx" int main() {     std::cout << "Exporting C++!" << std::endl;     std::cout << "Chapter 17, Demo 03 - MUD Game Programming" << std::endl;     Py_Initialize();                // initialize python     // initialize SWIGME module:     init_SWIGME();     // Import and run swiggy:     PyRun_SimpleString( "import swiggy" );     Py_Finalize();                  // shut down python     return 0; } 

Even though SWIG generated a .cxx module file, I've #includ ed it here like a header file, because the module generated a function named init_SWIGME. I need to call this function to inform the interpreter of the SWIGME module, but I don't know about that function, since it's not in a header. It exists only within the .cxx file.

Now you can compile the demo like all the other Python demos, and run it! You should get output that looks like this:

NOTE

Since you're treating the SWIGME_wrap.cxx file as a header, rather than a module, you need to make sure you don't compile it like a module, but rather, keep treating it like a header file. There are other ways around this limitation of course, but this is the easiest .

 Exporting C++! Chapter 17, Demo 03 - MUD Game Programming Result of SWIGME.SWIGFunction: This has been brought to you by the letter C Creating SWIGME.SWIGClass of 10: My Value is 10 Creating SWIGME.SWIGClass of 42: My Value is 42 

Ta-da! Isn't that cool?

[ LiB ]


MUD Game Programming
MUD Game Programming (Premier Press Game Development)
ISBN: 1592000908
EAN: 2147483647
Year: 2003
Pages: 147
Authors: Ron Penton

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net