24.3 Embedding Python
If you
have an application already written in C or C++ (or any other classic
compiled language), you may want to embed Python as your
application's scripting language. To embed Python in
languages other than C, the other language must be able to call C
functions. In the following, I cover only the C view of things, since
other languages vary widely regarding what you have to do in order to
call C functions from them.
24.3.1 Installing Resident Extension Modules
In order for Python scripts to
communicate with your application, your application must supply
extension modules with Python-accessible functions and classes that
expose your application's functionality. If these
modules are linked with your application rather than residing in
dynamic libraries that Python can load when necessary, register your
modules with Python as additional built-in modules by calling the
PyImport_AppendInittab C API function.
int PyImport_AppendInittab(char* name,void (*initfunc)(void))
|
|
name is the module name, which Python
scripts use in import statements to access the
module. initfunc is the module
initialization function, taking no argument and returning no result,
as covered earlier in this chapter (i.e.,
initfunc is the module's
function that would be named
initname for a normal
extension module residing in a dynamic library).
PyImport_AppendInittab must be called before
calling Py_Initialize.
24.3.2 Setting Arguments
You may want to set the program name
and arguments, which Python scripts can access as
sys.argv, by calling either or both of the
following C API functions.
void Py_SetProgramName(char* name)
|
|
Sets the program name, which Python scripts can access as
sys.argv[0]. Must be called before calling
Py_Initialize.
void PySys_SetArgv(int argc,char** argv)
|
|
Sets the program arguments, which Python
scripts can access as sys.argv[1:]. Must be called
after calling Py_Initialize.
24.3.3 Python Initialization and Finalization
After installing
extra built-in modules and optionally setting the program name, your
application initializes Python. At the end, when Python is no longer
needed, your application finalizes Python. The relevant functions in
the C API are as follows.
Frees all memory and other resources that Python is able to free. You
should not make other Python C API calls after calling this function.
Initializes the Python environment. Make no other Python C API call
before this one, except PyImport_AppendInittab and
Py_SetProgramName, as covered earlier in this
chapter.
24.3.4 Running Python Code
Your application can run Python
source code from a character string or from a file. To run or compile
Python source code, choose the mode of execution as one of the
following three constants defined in Python.h:
- Py_eval_input
-
The code is an expression to evaluate (like passing
'eval' to Python built-in function
compile)
- Py_file_input
-
The code is a block of one or more statements to execute (like
'exec' for compile—just
like in that case, a trailing '\n' must close
compound statements)
- Py_single_input
-
The code is a single statement for interactive execution (like
'single' for
compile—implicitly outputs the results of
expression statements)
Running Python source code directly is similar to passing a source
code string to Python statement exec or built-in
function eval, or a source code file to built-in
function execfile. Two general functions you can
use for this task are the following.
PyObject* PyRun_File(FILE* fp,char* filename,int start,
PyObject* globals,PyObject* locals)
|
|
fp is a file of source code open for
reading. filename is the name of the file,
to use in error messages. start is one of
the constants that define execution mode.
globals and
locals are dictionaries (may be the same
dictionary twice) to use as global and local namespace for the
execution. Returns the result of the expression when
start is Py_eval_input,
a new reference to Py_None otherwise, or
NULL to indicate that an exception has been raised
(often, but not always, due to a syntax error).
PyObject* PyRun_String(char* astring,int start,
PyObject* globals,PyObject* locals)
|
|
Like PyRun_File, but the source code is in
null-terminated string astring.
Dictionaries locals and
globals are often new, empty dictionaries
(most conveniently built by Py_BuildValue("{}"))
or the dictionary of a module. PyImport_Import is
a convenient way to obtain an existing module object;
PyModule_GetDict obtains a
module's dictionary. Sometimes you want to create a
new module object on the fly and populate it with
PyRun_ calls. To create a new, empty module, you
can use the PyModule_New C API function.
PyObject* PyModule_New(char* name)
|
|
Returns a new, empty module object for a
module named name. Before the new object
is usable, you must add to the object a string attribute named
_ _file_ _. For example:
PyObject* newmod = PyModule_New("mymodule");
PyModule_AddStringConstant(newmod, "__file_ _",
"<synthetic>"); After this code is run, module object
newmod is ready; you can obtain the
module's dictionary with
PyModule_GetDict(newmod)
and pass it directly to such functions as
PyRun_String as the
globals and possibly also the
locals argument.
To run Python code repeatedly, and to discern the diagnosis of syntax
errors from that of runtime exceptions raised by the code when it
runs, you can compile the Python source to a code object, then keep
the code object and run it repeatedly. This is just as true when
using the C API as when dynamically executing from Python, as covered
in Chapter 13. Two C API functions you can use for
this task are the following.
PyObject* Py_CompileString(char* code,char* filename,int start)
|
|
code is a null-terminated
string of source code. filename is the
name of the file, to use in error messages.
start is one of the constants that define
execution mode. Returns the Python code object containing the
bytecode, or NULL for syntax errors.
PyObject* PyEval_EvalCode(PyObject* co,PyObject* globals,
PyObject* locals)
|
|
co is a Python code object, as returned by
Py_CompileString, for example.
globals and
locals are dictionaries (may be the same
dictionary twice) to use as global and local namespace for the
execution. Returns the result of the expression when
co was compiled with
Py_eval_input, a new reference to
Py_None otherwise, or NULL to
indicate the execution has raised an exception.
|