It can be done a number of ways. Perhaps the most straightforward
way is to:
- wrap the C++ methods (and new/delete operations) in
'extern "C"' functions;
- make a Python C-extension modules that exports the C
wrappers to Python;
- define a stub class in Python to serve as the interface
to the C extension module functions.
Here's an extremely simple example:
(1) The C++ class (the one you want to use in Python):
class Simple {
public:
void show(char *message) { cout << message }
}
(2) The C-compatible wrapper functions (coded in C++):
#include <Simple.h>
extern "C" Simple * new_Simple()
{ return new Simple; }
extern "C" void del_Simple(Simple *obj)
{ delete obj; }
extern "C" void show_Simple(Simple *obj, char *message)
{ obj->show(message); }
(3) The C extension module (only the new/show parts are shown here)
extern char *new_Simple(); // defeat C++ type checking
extern void show_Simple(char *obj, char *msg)
static object *import_new_Simple(object *self, object *args)
{
char *obj = new_Printer(); // a char* in C
return mkvalue("i", obj); // an int in python
}
static object *import_show_Simple(object *self, object *args)
{
char *obj, *msg;
if (!getargs(args, "(is)", &obj, &msg))
return NULL;
show_Simple(obj, msg); // call C++ method for 'obj'
INCREF(None);
return None;
}
static struct methodlist Simple_methods[] = {
{"new_Simple", import_new_Simple},
{"show_Simple", import_show_Simple}, ...
// the usual 'methodlist' name/function table and init_Simple()
// start-up function; see Python extension manuals for details
(4) The Python stub class module: Simple.py
from _Simple import *
class Simple:
def __init__(self):
self._base = new_Simple() # store C++ superclass obj
def __del__(self):
del_Simple(self._base)
def show(self, message):
show_Simple(self._base, message)
(5) The Python client code:
from Simple import Simple
x = Simple()
x.show('Hello world!') # call the C++ method...
x = 0 (or del x) # calls __del__
A few notes:
- Part 3 is a normal C extension module, with static wrapper functions
that call the extern C++ wrappers, after converting Python arguments
to C form (getargs). Passes the C++ class instance to Python as an int
object, extract it as an int later.
- This is a really simple example, but scales up; for instance, to add
return types from C++ methods, you just add mkvalue() calls in the
C extension module wrappers. Similarly, C++ constructors can get
arguments,...
- It's not generally possible to support all of C++'s functionality
in Python. But you can at least handle new, delete, and method calls.
C++'s "esoteric" fetaures are harder; for instance, templates, operator
and function overloading, etc., is hard across language boundaries.
- If you want to support C++ virtual functions, there's more work to be
done: one solution is to define a C++ stub subclass, with definitions
for the virtuals which call back to the Python system (call_object, etc.)
- You can also export Python classes to C++; this is a bit harder, so
I won't go into it here...
Although I don't like to discuss work-in-progress until it's finished,
I'm working on a system that automatically generates all the code above
(and also handles simpler function-level integration). Basically, you
define your language integrations in a interface-description-language
that's 'compiled' into the appropriate code (which you then compile with
C and/or C++ compilers-- which gets around C++'s name-mangling). It's
not all that hard to do, and I'd be surprised if someone else isn't
doing something similar. More details as they emerge...
Hope this helps.
Mark Lutz