This looks a reasonable approach. The runtime will need to call the
extension to load it's part of the model. So ModelLoader will need to know
which library to call for a particular implementation type. The mechanism
should be the same for all implementation types so the existing
implementation.cpp should be refactored and not hard wired into the core.

I think it would be good to prototype this in a branch to experiment with
what works and what doesn't!

It may be worth considering defining the extensions as composites???

Cheers,


On 14/08/06, Andrew Borley <[EMAIL PROTECTED]> wrote:

Hi All,

I've been thinking a bit more about how we could do extensions.
Specifically, I've been working through what would be needed to add a new
component language binding in to Tuscany. I'm basing this on adding
support
for components written in Python, as this is a language that is widely
used,
extensible, embeddable and includes introspection.

To call a method in a Python module all we would need in the .composite
file
is something like the following information:
   <component name="DivideServiceComponent">
       <implementation.python module="DivideModule"
path="/path/to/python/module"/>
   </component>

The Python module will be in a file at
"/path/to/python/module/DivideModule.py" and would have a method that
implements a divide operation.

Python's introspection can find the correct method and describe the method
arguments and return types, so there is no requirement for code generated
via SCAGEN here (other languages may well need generated code).

We therefore need a way to extend the assembly model with the <
implementation.python> element and a way to extend Tuscany so that when it
finds an <implementation.python> element, it knows to call a library that
will invoke the Python code.

So to list things out we need to:

1) Define extensions for Tuscany in some way - perhaps a "Tuscany.config"
file that could have a schema like:
<tuscany-config>
<extension type="implementation or servicebinding or referencebinding or
interface"
   suffix="xs:NCName"
   library="xs:NCName"
   path="xs:NCName"?
   schema="xs:NCName"?>*
   <parameter name="xs:NCName">*
     some-parameter-value
   </parameter>
</extension>
</tuscany-config>

So for example, a Python component langauge implementation extension like
this:
<tuscany-config>
<extension type="implementation" suffix="python" library="tuscany-python"
path="/path/to/python/tuscany/extension/library"
   schema="xsd/tuscany-impl-python.xsd">
   <parameter name="pythonroot">/path/to/python/installation</parameter>
</extension>
</tuscany-config>

would have a library named
/path/to/python/tuscany/extension/library/libtuscany-python.so and a
schema
to define the <implementation.python> element at
/path/to/python/tuscany/extension/library/xsd/tuscany-impl-python.xsd. The
library would be initialised with a parameter named pythonroot with value
/path/to/python/installation.


2) Tuscany will need changing to:
a) register any schemas named in the "Tuscany.config" file
b) when the .composite files are read, notice the <implementation.python>
element and load and initialise the specified extension library with the
contents of the <implementation.python> element and the parameters from
the
"Tuscany.config" file
c) when the component is invoked, call the extension library with a
tuscany::sca::Operation object. The extension will find the appropriate
operation in the Python module, find the parameter and return types that
the
operation expects, map the C++ types to Python types, invoke the operation
and finally map the return type from Python to C++.


3) Create an extension to Python that will add support for invoking
references from Python components.
e.g. enable the Python equivalent of:
   // Get the current ComponentContext
   osoa::sca::ComponentContext myContext =
osoa::sca::ComponentContext::getCurrent();

   // Find the required service, as referenced in
CalculatorImpl.componentType
   DivideService* divideService =
(DivideService*)myContext.getService("divideService");

   // Finally, invoke the service
   result = divideService->divide(arg1, arg2);


How does this sound as a start to enabling some extensions in SCACPP?
I'm happy to get going implementing this, but it may be worth me working
in
a branch as there'll be lots of changes (& I don't yet have my committer
access).

Cheers

Andrew




--
Pete

Reply via email to