Mailing List Archive

Embedded Late Binding
I am in the process of embedding python into a Win32 text
editor. The plan is to allow the text editor to be control
using the python scripting langauge.

So far I have managed to build the python source into a DLL
and the editor is happily running python scripts and capturing
the error and output messages produced.

I have also managed to extend the intepreter using the standard
approach shown below:

static struct PyMethodDef editor_functions[] =
{
{ "get_line_number", MacroPython::get_line_number, 1 },
{ "set_line_number", MacroPython::set_line_number, 1 },
{ 0, 0, 0 },
};

void MacroPython::initialise()
{
Py_Initialize();
PyImport_AddModule("editor");
Py_InitModule("editor", editor_functions);
}

and these functions are also working well.

But I now have a question that I have not been able to find
the answer. The editor that I am hoping to control has over
400 functions all with and identical interface. For example:

FileOpen(); /* open a new file */
FileClose(); /* close the current file */
FileNew(); /* create a new file */
... etc etc

and these are contained within the editor EXE file. I am not
sure what is the best way to have the the interpreter recognize
these editor functions. I know I could add all 400 functions to
the static PyMethodDef structure but I really do not want to do
this since this means that the DLL and the EXE are effectively
hard coded.

What I am looking for is some sort of dynamic runtime linking
or some sort of late binding. The reason is, I want a method
where if the EXE file changes (ie new functions get add) the
new version EXE can still use the old version DLL without any
loss of functionality.

What I was hoping for was something like:

static struct PyMethodDef editor_functions[] =
{
{ "get_line_number", MacroPython::get_line_number, 1 },
{ "set_line_number", MacroPython::set_line_number, 1 },
{ "FileClose" , MacroPython::edit_func , 1 },
{ "FileEdit" , MacroPython::edit_func , 1 },
{ "FileNew" , MacroPython::edit_func , 1 },
{ ......................... },
{ 0, 0, 0 },
};

and then somehow in the C source:

PyObject *MacroPython::edit_func(PyObject *self, PyObject *args)
{
PyObject *pObject = 0;

if (PyArg_ParseTuple(args, ""))
{
/* somehow get the function name???? */
char *function_name = ???? (ie FileNew, FileOpen etc);

/* this part is easy enough todo */
call editor passing(function_name);
}
return pObject;
}


Can anyone tell me if this possible with Python 1.5.1?

Or is there a better way to achieve a similar result?

Thanks in advance.

Jussi Jumppanen
Home Page: http://ourworld.compuserve.com/homepages/jussi/
Embedded Late Binding [ In reply to ]
2 things come to mind here.

* Simplest may be to use the pre-processor. something like:
#define MAKE_FUNC(FuncName) \
static PyObject *Py##FuncName(PyObject *self, PyObject *args) \
blah blah \
rc = FuncName() \
blah blah\

MAKE_FUNC(OnFileNew);
MAKE_FUNC(OnFileSave);

You still have 400 methods to expose, but they get a lot smaller :-)

Alternatively, this is a bit more complex:
* Create a new "editor function" object. This would be a Python object that
has a tp_call slot. The module or object getattr() call could create and
return one of these objects. Eg:
PyObject *getattr(char *attr)
{
if (IsEditorFuncName(attr))
return PyEditorFunction(attr);
}

The 3rd of the 2 alternatives :-)
* Provide a Python wrapper class. Instead of dealing with Python modules
and functions natively, work with classes. This is similar to the above
option, but you move the logic into the Python code.

Hope this makes some sense, and at least points you to the right path for
your project...

Mark.

Jussi Jumppanen wrote in message <3719D318.1267@iname.com>...
> static struct PyMethodDef editor_functions[] =
> {
> { "get_line_number", MacroPython::get_line_number, 1 },
> { "set_line_number", MacroPython::set_line_number, 1 },
> { "FileClose" , MacroPython::edit_func , 1 },
> { "FileEdit" , MacroPython::edit_func , 1 },
> { "FileNew" , MacroPython::edit_func , 1 },
> { ......................... },
> { 0, 0, 0 },
> };
>
>and then somehow in the C source:
>
> PyObject *MacroPython::edit_func(PyObject *self, PyObject *args)
> {
> PyObject *pObject = 0;
>
> if (PyArg_ParseTuple(args, ""))
> {
> /* somehow get the function name???? */
> char *function_name = ???? (ie FileNew, FileOpen etc);
>
> /* this part is easy enough todo */
> call editor passing(function_name);
> }
> return pObject;
> }
>
>
>Can anyone tell me if this possible with Python 1.5.1?
>
>Or is there a better way to achieve a similar result?
>
>Thanks in advance.
>
>Jussi Jumppanen
>Home Page: http://ourworld.compuserve.com/homepages/jussi/