Re: embedding, getargs/mkvalue asymmetry

Hammond, Mark (MHammond@jm.cmutual.com.au)
Wed, 15 Feb 95 12:43:00 PST

> I wish I had the luxury of structuring my system the way you
> can. It sounds like you really have a Python system, with
> 'python-on-top', where the GUI API lives as a C extension
> layer; embedding only comes up when routing callbacks
> generated in a C system back to Python. Right?
Correct.

> Unfortunately, in my case, there's no way to grab onto a Python
> executable object ahead of time. It's a big C (well, really C++)
> system, which only calls Python functions or expression strings
> at strategic spots, to delegate selected validations and actions
> to Python. [The idea is to support on-site customization without
> shipping C/C++ library source code.]
>
> In your system, Python code "registers" a function object for
> call_object. This won't work for me-- no Python code is run until
> the embedded routine is invoked. [I'd be happy to rewrite our
> framework in Python, but management probably won't bite... :-)]

I would have thought the same solution can hold. Obviously I dont userstand
your application fully, but my first thoughts would be to:
* provide a really small C extension module to Python. This only consists
of "register" functions. This maps between an internal C name to the Python
function.
* Add "application startup" to your list of strategic spots, so the Python
objects can be registerd. This need only be an "import apphooks.py" or
whatever.
* When you need to "call Python functions or expression strings at strategic
spots", rather than calling by name, look up a map, and get a Python
object/string.

This would seem to have a number of benefits. The biggest is that the user
will not need to modify your code at all, just (maybe) derive from it.

For example - lets say you provide "customise.py". This contains:
def SomeExpression():
return something1 + something2 * something3

If the string "customise.SomeExpression" is effectively hard-coded in 'C',
users will have no choice but to modify your Python code.

However, my approach would allow:
--
# mycust.py
import customise.py

def MyExpression():
return customise.SomeExpression() * 2
--
(classes and deriving would work the same way (my preferred approach) with
the only problem with classes being how to construct the users object,
rather than yours, but this too is solvable.)

This way, only the code that registers the function needs be modified.
eg
---
# startup.py
import yourCext
# -- the following 2 lines have been changed from the version provided
# -- with the application.
#import customise
#yourCext.RegisterCallback(yourCext.THE_EXPRESSION,customise.SomeExpression)

# -- replaced with these 2 lines!
import mycust
yourCext.RegisterCallback( yourCext.THE_EXPRESSION, mycust.MyExpression )
--

The biggest benefit is to your users. If you change "customise.py" between
releases, your users will likely not have changed the file, so integrating
is less hassle.

> So, all I've got is a code string, or the module/function
> name of a routine. Now, I could pre-import the modules, and
This is primarily for functions, but the same technique could be used for
code strings too.

Somehow, it doesnt seem right for magic function names to be imbedded in the
application C code. Would the above be an option?

Mark (MHammond@cmutual.com.au)