[C++-sig] Re: Exposing C++ objects to Python at runtime
David Abrahams
dave at boost-consulting.com
Tue Nov 25 04:52:29 CET 2003
Raoul Gough <RaoulGough at yahoo.co.uk> writes:
> Jonathan Warrington <jon at shirwin.com> writes:
>
>> Ah, ok I think I see where the communication problem was now.
>>
>> What I was wanting to do, was have it so that my other components
>> would only know of that scripting engine interface, and use that to
>> register themselves at runtime when they are created, and therefore if
>> my XYZ class changes all I have to do is recompile that. Not have to
>> generate new Boost.Python registration code, and recompile that
>> wrapper.
>>
>> So,
>> App Starts
>> App creates an instance of Scripting Engine
>> App creates an instance of class XYZ
>> App passes scripting engine to XYZ->Init()
>> XYZ registers what it wants to be scriptable as scriptable
>
> Well, I don't know how realistic this is.
It can be done, and something which provides language-independent
wrapping syntax is surely worthwhile. I don't know if it's worthwhile
to do it with runtime polymorphism in this way.
> IIUC, you want some kind of
> an abstract interface that allows you to add new functions, object
> types and methods to various scripting engines. In this way, your
> classes can expose themselves to any of the engines, while having
> compile-time dependencies only on the abstract interface.
>
> So consider the following:
>
>>>> //Script function takes an arg count, an arg array, and returns a
>>>> //value
>>>> typedef void (*SCRIPT_FUNCTION)( int, ScriptVal**, ScriptVal* );
>>>> struct SW_ScriptEngine{
>>>> virtual void initialize() = 0;
>>>> virtual void release() = 0;
>>>> virtual ScriptVal* executeScript(String script) = 0;
>>>> virtual bool registerFunction(String name, SCRIPT_FUNCTION
>>>> func, String moduleName) = 0;
>>>>};
>
> class my_class {
> void function1(int);
> int function2() const;
>
> void register_self (SW_ScriptEngine *eng_ptr) {
> eng_ptr->registerFunction (&function1);
> eng_ptr->registerFunction (&function2);
> }
> };
>
> Now the type of function1 is "void (my_class::*)(int)" and the type of
> function2 is "int (my_class::*)() const". How is registerFunction
> going to be able to deal with those member functions (and all possible
> others)?
It's not that hard to imagine. registerFunction just needs to
generate a scripting-language-independent wrapper around the member
function which provides the means to invoke it and a way to get the
arguments initialized... something like:
struct function
{
virtual ~function() {}
virtual std::size_t arity() = 0;
virtual std::type_info const& result_type() = 0;
virtual std::type_info const* const* arg_types() = 0;
virtual void invoke(
void* const* args_storage, void* result_storage) = 0;
};
It's then the engine's job to line up the language specific converters
for the types of the arguments and result and build a wrapper around
*that*. In fact, now that I write it down it looks to me as though
Boost.Python could be organized in roughly this way at little extra
cost. Maybe in version 3... ;->
The biggest problem is that there are interfaces which really do
require you to touch language-specific components in order to bind
them well.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list