<!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<link rel=
"STYLESHEET" href=
"ext.css" type='text/css'
/>
<link rel=
"SHORTCUT ICON" href=
"../icons/pyfav.png" type=
"image/png" />
<link rel='start' href='../index.html' title='Python Documentation Index'
/>
<link rel=
"first" href=
"ext.html" title='Extending and Embedding the Python Interpreter'
/>
<link rel='contents' href='contents.html'
title=
"Contents" />
<link rel='last' href='about.html' title='About this document...'
/>
<link rel='help' href='about.html' title='About this document...'
/>
<link rel=
"prev" href=
"cplusplus.html" />
<link rel=
"parent" href=
"intro.html" />
<link rel=
"next" href=
"defining-new-types.html" />
<meta name='aesop' content='information'
/>
<title>1.12 Providing a C API for an Extension Module
<div id='top-navigation-panel' xml:id='top-navigation-panel'
>
<table align=
"center" width=
"100%" cellpadding=
"0" cellspacing=
"2">
<td class='online-navigation'
><a rel=
"prev" title=
"1.11 Writing Extensions in"
href=
"cplusplus.html"><img src='../icons/previous.png'
border='
0' height='
32' alt='Previous Page' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"parent" title=
"1. Extending Python with"
href=
"intro.html"><img src='../icons/up.png'
border='
0' height='
32' alt='Up One Level' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"next" title=
"2. Defining New Types"
href=
"defining-new-types.html"><img src='../icons/next.png'
border='
0' height='
32' alt='Next Page' width='
32'
/></A></td>
<td align=
"center" width=
"100%">Extending and Embedding the Python Interpreter
</td>
<td class='online-navigation'
><a rel=
"contents" title=
"Table of Contents"
href=
"contents.html"><img src='../icons/contents.png'
border='
0' height='
32' alt='Contents' width='
32'
/></A></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<div class='online-navigation'
>
<b class=
"navlabel">Previous:
</b>
<a class=
"sectref" rel=
"prev" href=
"cplusplus.html">1.11 Writing Extensions in
</A>
<b class=
"navlabel">Up:
</b>
<a class=
"sectref" rel=
"parent" href=
"intro.html">1. Extending Python with
</A>
<b class=
"navlabel">Next:
</b>
<a class=
"sectref" rel=
"next" href=
"defining-new-types.html">2. Defining New Types
</A>
<!--End of Navigation Panel-->
<H1><A NAME=
"SECTION0031200000000000000000"></A><A NAME=
"using-cobjects"></A>
1.12 Providing a C API for an Extension Module
Many extension modules just provide new functions and types to be
used from Python, but sometimes the code in an extension module can
be useful for other extension modules. For example, an extension
module could implement a type ``collection'' which works like lists
without order. Just like the standard Python list type has a C API
which permits extension modules to create and manipulate lists, this
new collection type should have a set of C functions for direct
manipulation from other extension modules.
At first sight this seems easy: just write the functions (without
declaring them
<tt class=
"keyword">static
</tt>, of course), provide an appropriate
header file, and document the C API. And in fact this would work if
all extension modules were always linked statically with the Python
interpreter. When modules are used as shared libraries, however, the
symbols defined in one module may not be visible to another module.
The details of visibility depend on the operating system; some systems
use one global namespace for the Python interpreter and all extension
modules (Windows, for example), whereas others require an explicit
list of imported symbols at module link time (AIX is one example), or
offer a choice of different strategies (most Unices). And even if
symbols are globally visible, the module whose functions one wishes to
call might not have been loaded yet!
Portability therefore requires not to make any assumptions about
symbol visibility. This means that all symbols in extension modules
should be declared
<tt class=
"keyword">static
</tt>, except for the module's
initialization function, in order to avoid name clashes with other
extension modules (as discussed in section
<A href=
"methodTable.html#methodTable">1.4</A>). And it
means that symbols that
<em>should
</em> be accessible from other
extension modules must be exported in a different way.
Python provides a special mechanism to pass C-level information
(pointers) from one extension module to another one: CObjects.
A CObject is a Python data type which stores a pointer (
<tt class=
"ctype">void
*
</tt>). CObjects can only be created and accessed via their C API, but
they can be passed around like any other Python object. In particular,
they can be assigned to a name in an extension module's namespace.
Other extension modules can then import this module, retrieve the
value of this name, and then retrieve the pointer from the CObject.
There are many ways in which CObjects can be used to export the C API
of an extension module. Each name could get its own CObject, or all C
API pointers could be stored in an array whose address is published in
a CObject. And the various tasks of storing and retrieving the pointers
can be distributed in different ways between the module providing the
code and the client modules.
The following example demonstrates an approach that puts most of the
burden on the writer of the exporting module, which is appropriate
for commonly used library modules. It stores all C API pointers
(just one in the example!) in an array of
<tt class=
"ctype">void
</tt> pointers which
becomes the value of a CObject. The header file corresponding to
the module provides a macro that takes care of importing the module
and retrieving its C API pointers; client modules only have to call
this macro before accessing the C API.
The exporting module is a modification of the
<tt class=
"module">spam
</tt> module from
section
<A href=
"simpleExample.html#simpleExample">1.1</A>. The function
<tt class=
"function">spam.system()
</tt>
does not call the C library function
<tt class=
"cfunction">system()
</tt> directly,
but a function
<tt class=
"cfunction">PySpam_System()
</tt>, which would of course do
something more complicated in reality (such as adding ``spam'' to
every command). This function
<tt class=
"cfunction">PySpam_System()
</tt> is also
exported to other extension modules.
The function
<tt class=
"cfunction">PySpam_System()
</tt> is a plain C function,
declared
<tt class=
"keyword">static
</tt> like everything else:
<div class=
"verbatim"><pre>
PySpam_System(const char *command)
The function
<tt class=
"cfunction">spam_system()
</tt> is modified in a trivial way:
<div class=
"verbatim"><pre>
spam_system(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args,
"s",
&command))
sts = PySpam_System(command);
return Py_BuildValue(
"i", sts);
In the beginning of the module, right after the line
<div class=
"verbatim"><pre>
two more lines must be added:
<div class=
"verbatim"><pre>
The
<code>#define
</code> is used to tell the header file that it is being
included in the exporting module, not a client module. Finally,
the module's initialization function must take care of initializing
<div class=
"verbatim"><pre>
static void *PySpam_API[PySpam_API_pointers];
m = Py_InitModule(
"spam", SpamMethods);
/* Initialize the C API pointer array */
PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
/* Create a CObject containing the API pointer array's address */
c_api_object = PyCObject_FromVoidPtr((void *)PySpam_API, NULL);
if (c_api_object != NULL)
PyModule_AddObject(m,
"_C_API", c_api_object);
Note that
<code>PySpam_API
</code> is declared
<tt class=
"keyword">static
</tt>; otherwise
the pointer array would disappear when
<tt class=
"function">initspam()
</tt> terminates!
The bulk of the work is in the header file
<span class=
"file">spammodule.h
</span>,
<div class=
"verbatim"><pre>
/* Header file for spammodule */
#define PySpam_System_NUM
0
#define PySpam_System_RETURN int
#define PySpam_System_PROTO (const char *command)
/* Total number of C API pointers */
#define PySpam_API_pointers
1
/* This section is used when compiling spammodule.c */
static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;
/* This section is used in modules that use spammodule's API */
static void **PySpam_API;
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
/* Return -
1 and set exception on error,
0 on success. */
PyObject *module = PyImport_ImportModule(
"spam");
PyObject *c_api_object = PyObject_GetAttrString(module,
"_C_API");
if (c_api_object == NULL)
if (PyCObject_Check(c_api_object))
PySpam_API = (void **)PyCObject_AsVoidPtr(c_api_object);
#endif /* !defined(Py_SPAMMODULE_H) */
All that a client module must do in order to have access to the
function
<tt class=
"cfunction">PySpam_System()
</tt> is to call the function (or
rather macro)
<tt class=
"cfunction">import_spam()
</tt> in its initialization
<div class=
"verbatim"><pre>
Py_InitModule(
"client", ClientMethods);
if (import_spam()
< 0)
/* additional initialization can happen here */
The main disadvantage of this approach is that the file
<span class=
"file">spammodule.h
</span> is rather complicated. However, the
basic structure is the same for each function that is
exported, so it has to be learned only once.
Finally it should be mentioned that CObjects offer additional
functionality, which is especially useful for memory allocation and
deallocation of the pointer stored in a CObject. The details
are described in the
<em class=
"citetitle"><a
Reference Manual
</a></em> in the section
``
<a class=
"ulink" href=
"../api/cObjects.html"
>CObjects
</a>'' and in the implementation
of CObjects (files
<span class=
"file">Include/cobject.h
</span> and
<span class=
"file">Objects/cobject.c
</span> in the Python source code distribution).
<div class='online-navigation'
>
<table align=
"center" width=
"100%" cellpadding=
"0" cellspacing=
"2">
<td class='online-navigation'
><a rel=
"prev" title=
"1.11 Writing Extensions in"
href=
"cplusplus.html"><img src='../icons/previous.png'
border='
0' height='
32' alt='Previous Page' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"parent" title=
"1. Extending Python with"
href=
"intro.html"><img src='../icons/up.png'
border='
0' height='
32' alt='Up One Level' width='
32'
/></A></td>
<td class='online-navigation'
><a rel=
"next" title=
"2. Defining New Types"
href=
"defining-new-types.html"><img src='../icons/next.png'
border='
0' height='
32' alt='Next Page' width='
32'
/></A></td>
<td align=
"center" width=
"100%">Extending and Embedding the Python Interpreter
</td>
<td class='online-navigation'
><a rel=
"contents" title=
"Table of Contents"
href=
"contents.html"><img src='../icons/contents.png'
border='
0' height='
32' alt='Contents' width='
32'
/></A></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<td class='online-navigation'
><img src='../icons/blank.png'
border='
0' height='
32' alt='' width='
32'
/></td>
<div class='online-navigation'
>
<b class=
"navlabel">Previous:
</b>
<a class=
"sectref" rel=
"prev" href=
"cplusplus.html">1.11 Writing Extensions in
</A>
<b class=
"navlabel">Up:
</b>
<a class=
"sectref" rel=
"parent" href=
"intro.html">1. Extending Python with
</A>
<b class=
"navlabel">Next:
</b>
<a class=
"sectref" rel=
"next" href=
"defining-new-types.html">2. Defining New Types
</A>
<span class=
"release-info">Release
2.4.2, documentation updated on
28 September
2005.
</span>
<!--End of Navigation Panel-->
See
<i><a href=
"about.html">About this document...
</a></i> for information on suggesting changes.