[Tutor] Re: embedding python in C --- big porblem

Michael P. Reilly arcege@shore.net
Wed, 15 Sep 1999 11:19:19 -0400 (EDT)


> edward wrote:
> 
> > Please mail me your response to ed_tsang@yahoo.com
> > thanks
> >
> > edward wrote:
> >
> > > Hi to all knowlegable python user out there:
> > > I'm am very new to python and have been having huge trouble in embdding
> > > python with c and extending python with c.
> > > here is what I am trying to do:
> > > 1) extending python in c
> > >    A)
> > >    *  create a function mymath(int a, int b)  in a file called mymath.c;

If you have a specific C function, then you can easily create a C
wrapper function for it.  You can do this with sig, or write the C
wrapper yourself.  In fact many of the standard C extension modules are
such wrappers.  The function would look like:

  PyObject *  /* return a Python object */
  pyfunc_mymath(self, args)
    PyObject *self, *args;
    { PyObject *result;
      int rc, a, b;

      if (!PyArg_ParseTuple(args, "ii:mymath", &a, &b))
        /* PyArg_ParseTuple sets the exception for you */
        return NULL;
      /* call your function */
      rc = mymath(a, b);
      /* construct a Python object from it */
      result = Py_BuildValue("i", rc);
      /* return the resulting Python object */
      return result;
    }

Now you just need to add the new wrapper function to the module listing
as described in the manuals:
  http://www.python.org/doc/current/ext/ext.html
You will need to create a new module to hold this new function (and
possibly others).

> > >    *  try to call mymath  function to add 1 & 2 from a pythohn script,

Import the module created above and call the function:
  >>> import mymod
  >>> print mymod.mymath(1, 2)
  3

> > >    * without recompling try to call mymath to add 3 and 4 from the
> > > python script

Call the function with other arguments within Python.
  >>> import mymod
  >>> mymod.mymath(1, 2)
  3
  >>> mymod.mymath(3, 4)
  7

> > >    *  without recompliing try to redefine mymath, so that I am
> > > subtracting this time

Well, you can not redefine the internal function of mymath - that is a
C function compiled into the module.  But the module IS a normal Python
namespace and namespaces can be changed:

  >>> import mymod
  >>> mymod.mymath(1, 2)
  3
  >>> mymod.mymath = lambda a, b: a - b
  >>> mymod.mymath(3, 4)
  -1

The name is redefined to be a Python lambda function instead of a
builtin C function.

> > >    * try to call mymath function to subtract 1 from 2
> > >    * without recompliing try to call mymath to subtract 3 from 4

> > >     B)
> > >     * create a structure which has two elements a and b,
> > >          a function initStruct(x,y)  to in a file called intiStruct.c.
> > > initStruct(x,y)  will initlize a    to     x, b to y value.
> > >      *  try  from a pythohn script, try to call the initStruct to
> > > intialise the stucture to 2 and 3

This is the same as above.

> > >     * without recompling try to call initStruct to intialise structure
> > > to 3 and 4 from the python script

> > > 2) embedding python to c
> > > A)
> > >   *  create a function mymath(int a, int b)  in a file called mymath.py
> > > ;

Creating a C function inside a Python module file?

Assuming you mean to create a Python function, then you can use:
  fp = fopen("commands.py", "r");
  PyRun_SimpleFile(fp, "commands.py");

This is about the same as `exec("commands.py")'.

Assuming that you mean to call a C function, you would need to code
this into the C program.  This is the same as above, except through the
C API instead of through a Python script:

  /* import the module */
  mymod = PyImport_ImportModule("mymod");
  /* get the mymod.initStruct */
  myfunc = PyObject_GetAttrString(mymod, "initStruct");
  /* call it */
  x = 2;
  result = PyObject_CallFunction(myfunc, "ii", x, 3);

> > >    *  try to call mymath  function to add 1 & 2 from a C program,
> > >    * without recompling try to call mymath to add 3 and 4 from the C
> > > program

That would need to be a C solution and not something for Python to
handle. E.g. reading from stdin, reading from file, reading from UI
form.

> > >    *  without recompliing try to redefine mymath, so that I am
> > > subtracting this time.

See the first section; again, we're talking about namespaces.  But you
have to write code to tell the program to redefine the name "mymath".

> > >    * try to call mymath function to subtract 1 from 2, from the C
> > > program
> > >    * without recompliing try to call mymath to subtract 3 from 4, from
> > > the C program

Most everything in this section means changing the C program, which
means recompiling, or changing the Python script file.

> > > Can any one help me on this please. Can you give me the complete working
> > > code on this matter. I really need all you expert help on this thing.
> > > thanks.

Considering there is little to go on, it's unlikely that you will get
"complete working code" from anyone.  Maybe you could repost what you
are looking to do in a more clearly defined manner.

> I have forgotten to ask one more question on this:
> Is it possible to compile the code such that the resultant will be just one
> excutable? (ie. python executable and the c exxcutable are residing in the
> same process)?

When you extend or embed Python with C (or another language), then you
get one executable (and possibly some dynamic loadables (.so, .dll,
etc. depending on how you build it)

> If that is the case, I suspect I cannot change the input parameters on the fly
> (ie: I cannot do something like having mymath doing addin and  then redefining
> the do substraction. without recmpling as in my questions below) Am I right on
> that?
> Thanks a gain

This would depend on what you have the program do.  You could have the
program define all of Python if you realllllly wanted (not that I would
suggest it).  The python interpreter, like just about any interpreter,
is just read-eval-print loop.  Your program could read input parameters
from any medium and use them within the program without recompiling (if
you designed the program to do that.)

I suggest you read the Python documentation thoroughly; specifically:
  http://www.python.org/doc/current/ext/ext.html, and
  http://www.python.org/doc/current/api/api.html, and possibly even
  http://starship.python.net/crew/arcege/extwriting/pyext.html.

  -Arcege

-- 
------------------------------------------------------------------------
| Michael P. Reilly, Release Engineer | Email: arcege@shore.net        |
| Salem, Mass. USA  01970             |                                |
------------------------------------------------------------------------