Learning Python - Unit 16, Embedding
Learning Python - Unit 16, Embedding
Embedding topics
♦ Calling objects
♦ Running code strings
♦ Registration techniques
♦ Other topics: errors, tools, etc.
♦ Callable objects
● Calling functions, classes, methods
♦ Code files
https://learning-python.com/class/Workbook/unit16.htm 1/23
10/11/2019 Learning Python: Unit 16, Embedding
Source Description
Modules fetching code by importing modules
Text files fetching code from simple text files
Registration letting Python pass code to a C extension
HTML tags extracting code from web pages
Databases fetching code from a database table
Processes receiving code over sockets
Construction building Python code in C at runtime
And so on system registries, etc.
file: main1.c
#include <Python.h>
main(argc, argv)
int argc;
char **argv;
{
/* This is the simplest embedding mode. */
/* Other API functions return results, */
/* accept namespace arguments, allow */
/* access to real Python objects, etc. */
/* Strings may be precompiled for speed. */
https://learning-python.com/class/Workbook/unit16.htm 3/23
10/11/2019 Learning Python: Unit 16, Embedding
% main1
Hello embedded world!
0 Hello, mlutz
1 Hello, mlutz
2 Hello, mlutz
3 Hello, mlutz
Bye embedded world!
file: Makefile.main1
# this file builds a C executable that embeds Python
# assuming no external module libs must be linked in
# works on Linux with a custom Python build tree
PY = /home/mark/python1.5.2-ddjcd/Python-1.5.2
PYLIB = $(PY)/libpython1.5.a
https://learning-python.com/class/Workbook/unit16.htm 4/23
10/11/2019 Learning Python: Unit 16, Embedding
basic1: basic1.o
cc basic1.o $(PYLIB) -g -export-dynamic -lm -ldl -o basic1
basic1.o: basic1.c
cc basic1.c -c -g $(PYINC)
class klass:
def method(self, x, y):
return "brave %s %s" % (x, y) # run me from C
file: objects1.c
#include <Python.h>
#include <stdio.h>
main() {
char *arg1="sir", *arg2="robin", *cstr;
PyObject *pmod, *pclass, *pargs, *pinst, *pmeth, *pres;
/* instance = module.klass() */
Py_Initialize();
pmod = PyImport_ImportModule("module");
pclass = PyObject_GetAttrString(pmod, "klass");
Py_DECREF(pmod);
pargs = Py_BuildValue("()");
pinst = PyEval_CallObject(pclass, pargs);
Py_DECREF(pclass);
Py_DECREF(pargs);
/* result = instance.method(x,y) */
pmeth = PyObject_GetAttrString(pinst, "method");
Py_DECREF(pinst);
pargs = Py_BuildValue("(ss)", arg1, arg2);
pres = PyEval_CallObject(pmeth, pargs);
Py_DECREF(pmeth);
Py_DECREF(pargs);
% objects1
brave sir robin
https://learning-python.com/class/Workbook/unit16.htm 6/23
10/11/2019 Learning Python: Unit 16, Embedding
main() {
char *arg1="sir", *arg2="robin", *cstr;
PyObject *pmod, *pclass, *pargs, *pinst, *pmeth, *pres;
/* instance = module.klass() */
Py_Initialize();
pmod = PyImport_ImportModule("module");
if (pmod == NULL)
error("Can't load module");
pclass = PyObject_GetAttrString(pmod, "klass");
Py_DECREF(pmod);
if (pclass == NULL)
error("Can't get module.klass");
pargs = Py_BuildValue("()");
if (pargs == NULL) {
Py_DECREF(pclass);
error("Can't build arguments list");
}
pinst = PyEval_CallObject(pclass, pargs);
Py_DECREF(pclass);
Py_DECREF(pargs);
if (pinst == NULL)
error("Error calling module.klass()");
/* result = instance.method(x,y) */
pmeth = PyObject_GetAttrString(pinst, "method");
Py_DECREF(pinst);
if (pmeth == NULL)
error("Can't fetch klass.method");
pargs = Py_BuildValue("(ss)", arg1, arg2);
if (pargs == NULL) {
Py_DECREF(pmeth);
error("Can't build arguments list");
}
pres = PyEval_CallObject(pmeth, pargs);
Py_DECREF(pmeth);
Py_DECREF(pargs);
if (pres == NULL)
error("Error calling klass.method");
https://learning-python.com/class/Workbook/unit16.htm 7/23
10/11/2019 Learning Python: Unit 16, Embedding
file: objects2.c
#include <stdio.h>
#include "pyembed.h"
main () {
int failflag;
PyObject *pinst;
char *arg1="sir", *arg2="robin", *cstr;
failflag =
Run_Function("module", "klass", /* module.klass() */
"O", &pinst, "()") /* result, args */
||
Run_Method(pinst, "method", /* pinst.method() */
"s", &cstr, /* result fmt/ptr */
"(ss)", arg1, arg2); /* args fmt/values*/
% objects2
brave sir robin
file codestring1.c
#include <Python.h> /* standard API defs */
main() {
/* error checking omitted! */
char *cstr;
PyObject *pstr, *pmod, *pdict;
Py_Initialize();
pdict = PyModule_GetDict(pmod);
pstr = PyRun_String("upper('spam') + '!'",
Py_eval_input, pdict, pdict);
/* convert result to C */
PyArg_Parse(pstr, "s", &cstr);
printf("%s\n", cstr);
Py_DECREF(pmod);
Py_DECREF(pstr); /* free exported objects */
}
% codestring1
SPAM!
file: codestring2.c
#include "pyembed.h"
#include <stdio.h>
main() {
char *cstr;
int err =
Run_Codestr(
PY_EXPRESSION, /* expr|stmt? */
"upper('spam') + '!'", "string", /* code,module */
"s", &cstr); /* expr result */
printf("%s\n", (!err) ? cstr : "Can't run string");
}
% codestring2
SPAM!
Copy-in-copy-out
validate.py
C code…
https://learning-python.com/class/Workbook/unit16.htm 10/23
10/11/2019 Learning Python: Unit 16, Embedding
file: basic4.c
#include <Python.h>
main() {
int cval;
PyObject *pdict, *pval;
Py_Initialize();
/* fetch dict['X'] */
pval = PyDict_GetItemString(pdict, "X");
PyArg_Parse(pval, "i", &cval); /* convert to C */
printf("%d\n", cval); /* result=101 */
Py_DECREF(pdict);
}
♦ A C extension module
https://learning-python.com/class/Workbook/unit16.htm 11/23
10/11/2019 Learning Python: Unit 16, Embedding
Registration implementation
file: cregister.c
#include <Python.h>
#include <stdlib.h>
/***********************************************/
/* 1) code to route events to Python object */
/* note that we could run strings here instead */
/***********************************************/
if (pres != NULL) {
/* use and decref handler result */
PyArg_Parse(pres, "s", &cres);
printf("%s\n", cres);
Py_DECREF(pres);
}
}
/*****************************************************/
/* 2) python extension module to register handlers */
/* python imports this module to set handler objects */
/*****************************************************/
static PyObject *
Register_Handler(PyObject *self, PyObject *args)
{
/* save Python callable object */
Py_XDECREF(Handler); /* called before? */
PyArg_Parse(args, "O", &Handler); /* one argument? */
https://learning-python.com/class/Workbook/unit16.htm 12/23
10/11/2019 Learning Python: Unit 16, Embedding
static PyObject *
Trigger_Event(PyObject *self, PyObject *args)
{
/* let Python simulate event caught by C */
static count = 0;
Route_Event("spam", count++);
Py_INCREF(Py_None);
return Py_None;
}
file: register.py
import cregister
https://learning-python.com/class/Workbook/unit16.htm 13/23
10/11/2019 Learning Python: Unit 16, Embedding
cregister.setHandler(function1)
for i in range(3):
cregister.triggerEvent() # simulate events caught by C
cregister.setHandler(function2)
for i in range(3):
cregister.triggerEvent() # routes events to function2
% python register.py
spam number 0...
spam number 1...
spam number 2...
spamspamspam
spamspamspamspam
spamspamspamspamspam
Registration tradeoffs
♦ +: Granularity
Associating actions with objects without external files
♦ -: Application structure
Requires Python on top, or extra embedding logic
♦ -: Complexity
Might require extra coding step to register code
♦ -: Reloading code
Difficult to reload without going through modules
cregister.so: cregister.c
$(Cc) cregister.c $(CFLAGS) -DDEBIG -KPIC -o cregister.o
ld -G cregister.o -o $@
environ.so: environ.c
$(Cc) environ.c $(CFLAGS) -KPIC -o environ.o
https://learning-python.com/class/Workbook/unit16.htm 14/23
10/11/2019 Learning Python: Unit 16, Embedding
ld -G environ.o -o $@
Linux
PY = /home/mark/python1.5.2-ddjcd/Python-1.5.2
PYINC = -I$(PY)/Include -I$(PY)
cregister.so: cregister.c
gcc cregister.c -g $(PYINC) -fpic -shared
♦ Using copy-in-copy-out
1. C copies X and Y values to variables in module M
2. C runs embedded code in module M’s name-space
3. C fetches the final values of the Python variables
https://learning-python.com/class/Workbook/unit16.htm 15/23
10/11/2019 Learning Python: Unit 16, Embedding
♦ ‘PyRun_File’, ‘PyRun_SimpleFile’
♦ Module imports and reloads
♦ system, popen, fork/exec
PyCodeObject*
Py_CompileString(char *string,
char *filename, int parsemode);
PyObject*
PyEval_EvalCode(PyCodeObject *code,
PyObject *globalnamesdict,
PyObject *localnamesdict);
♦ Python libraries
● Don’t need to be recompiled by the C++ compiler to link: API entry
points are all extern “C”
Resources:
https://learning-python.com/class/Workbook/unit16.htm 17/23
10/11/2019 Learning Python: Unit 16, Embedding
♦ Other references
● Programming Python, Editions 2+
https://learning-python.com/class/Workbook/unit16.htm 18/23
10/11/2019 Learning Python: Unit 16, Embedding
file: pyerrors.c
#include <Python.h>
#include <stdio.h>
char save_error_type[1024], save_error_info[1024];
PyerrorHandler(char *msgFromC)
{
/* process Python-related errors */
/* call after Python API raises an exception */
pystring = NULL;
if (errobj != NULL &&
(pystring = PyObject_Str(errobj)) != NULL &&
(PyString_Check(pystring))
)
strcpy(save_error_type, PyString_AsString(pystring));
else
https://learning-python.com/class/Workbook/unit16.htm 19/23
10/11/2019 Learning Python: Unit 16, Embedding
pystring = NULL;
if (errdata != NULL &&
(pystring = PyObject_Str(errdata)) != NULL &&
(PyString_Check(pystring))
)
strcpy(save_error_info, PyString_AsString(pystring));
else
strcpy(save_error_info, "<unknown exception data>");
Py_XDECREF(pystring);
♦ SWIG
● Generates Python interfaces to external C/C++ libraries
● Uses C/C++ declarations and interface description files
● For C++ class: generates C type + Python wrapper class
● See unit 15, the book Programming Python editions 2+, and
http://www.swig.org/
♦ ILU
● Implements CORBA distributed-object systems
● Uses interface description files
● Platform and language independent
♦ Modulator
● Tkinter GUI: generates skeleton C module/type files
● Users fill in the blanks with application-specific logic
● An old idea, which has been revived recently (forgetting history
much?)
https://learning-python.com/class/Workbook/unit16.htm 21/23
10/11/2019 Learning Python: Unit 16, Embedding
Lab Session 12
Click here to go to lab exercises
https://learning-python.com/class/Workbook/unit16.htm 23/23