[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