[C++-sig] Is this use of Boost.Python safe?

Matthew Bray mat at matbray.com
Wed Sep 10 16:26:18 CEST 2003


[originally posted to the boost.user list]

I have a question regarding the use of Boost.Python. What I would like 
to do is to provide a simple scripting interface to an application in 
much the same way as Microsoft use Visual Basic within much of their 
product line (e.g. Excel) to provide direct access to the applications 
object model.
My design is stunningly rendered below,

+-------------------------+
| Application--+          |
|              |          | Dynamically +---------------+
|              v          |   Linked    | Python Module |
|    +--->ObjectModel<------------------|               |
|    |                    |             +---------------+
| +---------------------+ |                     |
| | Python Interpretter |<----------------------+
| |                     | | ">>> import ..."
| +---------------------+ |
+-------------------------+

What we have firstly is a our python module, in this case it exports a 
simple class 'ObjectModel' with various functions, sub objects and 
whatever else is required for the application to run. This is our Object 
Model, and is usable from the python interpretter on the command line.
For what we have in mind however is for the python interpretter to be 
running inside the application (through use of the Py* functions from 
the python API and use of the relevant parts of Boost.Python - handle<>, 
object).
What I want is for the application and the python instance to share the 
object model, for the interpretter to have knowledge of the ObjectModel 
it is simply imported from the python module. The application itself is 
linked against the python module in order to use ObjectModel (the 
relevant compiler specific code is inserted so that the ObjectModel 
class is exported/imported - __declspec(dllexport) and dllimport under 
Visual C++).
With this setup, it is now possible to create an instance of ObjectModel 
within the python interpretter and use extract<ObjectModel*>(...) in 
order to get access to it within the application, no doubt it is also 
possible to create the ObjectModel within the application and pass it to 
the python interpretter to use it there. Now my question basically 
regards pitfalls in this approach, there are two instances of the Python 
Module in use here but I'm sure that as long as care is taken to ensure 
the ObjectModel is destructed on the same heap that it was created on 
then there shall be no problems. Is there any other, possibly better way 
to do this perhaps - e.g. without requiring the use of the module at 
all, simply passing the Boost.Python class descriptions directly to the 
embedded interpretter. A simple test harness I have /appears/ to work 
fine with the above design.

Here's an extremely cut down bit of code that should show kind of what 
I'm working on if I'm being a little unclear:

my_module.hpp - this is the class that is in the python module that we 
shall have access to within python and our application:

struct PLATFORM_SPECIFIC_DLL_EXPORT_COMMAND ObjectModel
{
     const char * name() const;
};

my_application.cpp - assume all the correct headers are included, the 
module is linked against etc:

int main(int argc,char ** argv)
{
     Py_Initialize();

     //initialize the environment
     handle<> main_module(borrowed(PyImport_AddModule("__main__")));
     handle<> main_namespace(
         borrowed(PyModule_GetDict(main_module.get())));

     //import our python module
     handle<>(PyRun_String("import my_module", Py_file_input,
         main_namespace.get(), main_namespace.get()) );

     //create a new instance of ObjectModel within python
     handle<>(PyRun_String("model = my_module.ObjectModel()",
         Py_file_input, main_namespace.get(), main_namespace.get()));

     //get the instance of ObjectModel and use it within our application
     object tmp(main_namespace);
     ObjectModel * model = extract<ObjectModel *>(tmp["model"]);

     //use the model, the function is dispatched to the dynamically
     //linked &ObjectModel::name method, not the python imported
     //instance.
     cout << model->name() << endl;

     Py_Finalize();
}


Mat.






More information about the Cplusplus-sig mailing list