Interrogate
Interrogate is a program to parse a body of C++ code and build up a table
of classes, methods, functions, and symbols found, for the purposes of
calling into the codebase via a non-C++ scripting language like Python (Scheme and Smalltalk were also tried at some point) The design of interrogate is such that it should be able to produce wrappers for any other language without too much trouble. You'll have to be responsible for writing and maintaining the interface layer to produce the wrappers, though.
In addition to identifying all the classes and their relationships,
interrogate will generate a wrapper function for each callable function.
The wrapper functions will be callable directly from the scripting language,
with no understanding of C++ necessary; these wrapper functions will in turn
call the actual C++ functions or methods.
Most exportable features of C++ are supported, including templates, default
parameters, and function overloading.
How to use it
There are a few steps involved in generating python wrappers using interrogate.
Steps for Interrogate:
- In this example it is assumed you have a header file called test.h and a source file called test.cxx.
- Run Interrogate on your .h file which will generate a test_igate.cxx and a test.in file, for example:
interrogate -oc test_igate.cxx -od test.in -python-native test.h
- Most likely, you want to specify more flags to the interrogate command, like -string, -fnames, -refcount, or -assert. Consult the interrogate help file for more information about that (run interrogate with -h option)
- Now, you will need to call interrogate_module and generate an interrogate_module.cxx file based on your two files from the previous step:
interrogate_module -oc test_module.cxx -python-native test.in
- Note that you can also run interrogate with the -do-module option which will automatically make sure interrogate_module gets called too.
- Now you can compile all your source files, and, the test_module.cxx and test_igate.cxx files.
- When you want to link your C++ files together to form a library, also include the _igate and _module object files. This will make sure it will include the python wrappers.
- You can now put it on your python path (or make sure it's in the same directory) and import it directly by the name of your library.
from libtest import TestClass
- Note: In python versions 2.5 and higher, you can not directly load .dll files on windows this way. You will either need to rename your dll into a pyd extension (which will load without problems, hopefully) or you need to preload your library using the imp module.
Calling Interrogate
This section will explain how to call interrogate and will briefly address the most important options. For the full documentation, however, refer to the interrogate help file (accessible by calling interrogate with the -h option).
When calling interrogate, you will need to include the -oc and -od options, which specify where the generated code and function tables, respectively, will be written.
The -module and -library options are used to specify the name of your module and library. These options are mainly code-organizational. You can omit both options.
With -D you can ignore or make interrogate interpret symbols differently. For example, if your code uses a non-standard C macro like __inline, you would need to call interrogate with -D__inline. Or, if you would like certain defines to be defined differently, you can use -Ddefvar=value.
Furthermore, there are a few special flags that you most likely want to include. There is the -string option, which treats the C++ char* and STL strings as special cases, and maps them to the scripting language's string equivalent, instead of a wrapper to basic_string<char>. The option -refcount makes the wrappers compatible with Panda3D's smart reference counting system, if your library depends on Panda3D you will want to include it too. The -assert option is just used for Python wrappers and specifies that when the C++ code throws an assert, this will be translated to an AssertionError exception in python.
Wrapper functions
There are three/four options that specify how to generate the wrapper functions:
- The -c option will generate function wrappers using the C calling convention. Any scripting language that can call a C function should be able to make advantage of the interrogate database.
- The -python option will generate function wrappers using the Python calling convention. In this case, the shared library will directly be loadable as python module (after interrogate_module is called), although C++ objects and methods will be converted into an object handle and a list of independent Python functions.
- The -python-native option generates true python objects for C++ objects, and translates all C++ methods to true Python methods. This is the option you will most likely want to use.
- There is also the -python-obj option, but I think it does the same as -python-native.
You can also specify a combination of any of those. If all are omitted, the default is -c.
Here's a small example:
interrogate -D__inline -DCPPPARSER -D__cplusplus -S/usr/include/panda3d/parser-inc -S/usr/include/ -I/usr/include/panda3d/
-oc myModule_igate.cxx -od myModule.in -fnames -string -refcount -assert -python-native
-module libMyModule -library libMyModule myModule.h
interrogate_module -oc myModule_module.cxx -module libMyModule
-library libMyModule -python-native myModule.in
More Information
- You can run the interrogate commands with the -h option to get a more detailed explanation of the options available.
- There is a sample C++ extension in the skel/ directory in the Panda3D source to use as reference and sandbox.
- David Rose, from Walt Disney VR Studio, has held a lecture about interrogate. You can watch a video recording of it here. (Recorded June 4, 2008)