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

David Abrahams dave at boost-consulting.com
Thu Sep 11 05:51:40 CEST 2003


Matthew Bray <mat at matbray.com> writes:

> [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++).

You can do that.  I'd be inclined to stick the ObjectModel code in a
separate DLL that's used by the App and the extension module, but
your way works.

> 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. 

Yes.

> Now my question basically regards pitfalls in this approach, there
> are two instances of the Python Module in use here 

Huh!?

What do you mean by "two instances"?


> 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. 

I wouldn't count on it.  Please elaborate on what you mean by the
above "two instances" remark.

> 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. 

See http://www.boost.org/libs/python/test/embedding.cpp.  Does that
help?

> 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();
       ^^^^^^^^^^^

This is a pitfall.  Boost.Python hasn't been made "finalize-safe",
yet.  Dirk Gerritts was working on it, but...

> }
>
>
> Mat.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com





More information about the Cplusplus-sig mailing list