Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / src / nas,5.n2.os.2 / lib / python / html / python / ext / using-cobjects.html
CommitLineData
86530b38
AT
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<html>
3<head>
4<link rel="STYLESHEET" href="ext.css" type='text/css' />
5<link rel="SHORTCUT ICON" href="../icons/pyfav.png" type="image/png" />
6<link rel='start' href='../index.html' title='Python Documentation Index' />
7<link rel="first" href="ext.html" title='Extending and Embedding the Python Interpreter' />
8<link rel='contents' href='contents.html' title="Contents" />
9<link rel='last' href='about.html' title='About this document...' />
10<link rel='help' href='about.html' title='About this document...' />
11<link rel="prev" href="cplusplus.html" />
12<link rel="parent" href="intro.html" />
13<link rel="next" href="defining-new-types.html" />
14<meta name='aesop' content='information' />
15<title>1.12 Providing a C API for an Extension Module
16</title>
17</head>
18<body>
19<DIV CLASS="navigation">
20<div id='top-navigation-panel' xml:id='top-navigation-panel'>
21<table align="center" width="100%" cellpadding="0" cellspacing="2">
22<tr>
23<td class='online-navigation'><a rel="prev" title="1.11 Writing Extensions in"
24 href="cplusplus.html"><img src='../icons/previous.png'
25 border='0' height='32' alt='Previous Page' width='32' /></A></td>
26<td class='online-navigation'><a rel="parent" title="1. Extending Python with"
27 href="intro.html"><img src='../icons/up.png'
28 border='0' height='32' alt='Up One Level' width='32' /></A></td>
29<td class='online-navigation'><a rel="next" title="2. Defining New Types"
30 href="defining-new-types.html"><img src='../icons/next.png'
31 border='0' height='32' alt='Next Page' width='32' /></A></td>
32<td align="center" width="100%">Extending and Embedding the Python Interpreter</td>
33<td class='online-navigation'><a rel="contents" title="Table of Contents"
34 href="contents.html"><img src='../icons/contents.png'
35 border='0' height='32' alt='Contents' width='32' /></A></td>
36<td class='online-navigation'><img src='../icons/blank.png'
37 border='0' height='32' alt='' width='32' /></td>
38<td class='online-navigation'><img src='../icons/blank.png'
39 border='0' height='32' alt='' width='32' /></td>
40</tr></table>
41<div class='online-navigation'>
42<b class="navlabel">Previous:</b>
43<a class="sectref" rel="prev" href="cplusplus.html">1.11 Writing Extensions in</A>
44<b class="navlabel">Up:</b>
45<a class="sectref" rel="parent" href="intro.html">1. Extending Python with</A>
46<b class="navlabel">Next:</b>
47<a class="sectref" rel="next" href="defining-new-types.html">2. Defining New Types</A>
48</div>
49<hr /></div>
50</DIV>
51<!--End of Navigation Panel-->
52
53<H1><A NAME="SECTION0031200000000000000000"></A><A NAME="using-cobjects"></A>
54<BR>
551.12 Providing a C API for an Extension Module
56
57</H1>
58
59<P>
60Many extension modules just provide new functions and types to be
61used from Python, but sometimes the code in an extension module can
62be useful for other extension modules. For example, an extension
63module could implement a type ``collection'' which works like lists
64without order. Just like the standard Python list type has a C API
65which permits extension modules to create and manipulate lists, this
66new collection type should have a set of C functions for direct
67manipulation from other extension modules.
68
69<P>
70At first sight this seems easy: just write the functions (without
71declaring them <tt class="keyword">static</tt>, of course), provide an appropriate
72header file, and document the C API. And in fact this would work if
73all extension modules were always linked statically with the Python
74interpreter. When modules are used as shared libraries, however, the
75symbols defined in one module may not be visible to another module.
76The details of visibility depend on the operating system; some systems
77use one global namespace for the Python interpreter and all extension
78modules (Windows, for example), whereas others require an explicit
79list of imported symbols at module link time (AIX is one example), or
80offer a choice of different strategies (most Unices). And even if
81symbols are globally visible, the module whose functions one wishes to
82call might not have been loaded yet!
83
84<P>
85Portability therefore requires not to make any assumptions about
86symbol visibility. This means that all symbols in extension modules
87should be declared <tt class="keyword">static</tt>, except for the module's
88initialization function, in order to avoid name clashes with other
89extension modules (as discussed in section&nbsp;<A href="methodTable.html#methodTable">1.4</A>). And it
90means that symbols that <em>should</em> be accessible from other
91extension modules must be exported in a different way.
92
93<P>
94Python provides a special mechanism to pass C-level information
95(pointers) from one extension module to another one: CObjects.
96A CObject is a Python data type which stores a pointer (<tt class="ctype">void
97*</tt>). CObjects can only be created and accessed via their C API, but
98they can be passed around like any other Python object. In particular,
99they can be assigned to a name in an extension module's namespace.
100Other extension modules can then import this module, retrieve the
101value of this name, and then retrieve the pointer from the CObject.
102
103<P>
104There are many ways in which CObjects can be used to export the C API
105of an extension module. Each name could get its own CObject, or all C
106API pointers could be stored in an array whose address is published in
107a CObject. And the various tasks of storing and retrieving the pointers
108can be distributed in different ways between the module providing the
109code and the client modules.
110
111<P>
112The following example demonstrates an approach that puts most of the
113burden on the writer of the exporting module, which is appropriate
114for commonly used library modules. It stores all C API pointers
115(just one in the example!) in an array of <tt class="ctype">void</tt> pointers which
116becomes the value of a CObject. The header file corresponding to
117the module provides a macro that takes care of importing the module
118and retrieving its C API pointers; client modules only have to call
119this macro before accessing the C API.
120
121<P>
122The exporting module is a modification of the <tt class="module">spam</tt> module from
123section&nbsp;<A href="simpleExample.html#simpleExample">1.1</A>. The function <tt class="function">spam.system()</tt>
124does not call the C library function <tt class="cfunction">system()</tt> directly,
125but a function <tt class="cfunction">PySpam_System()</tt>, which would of course do
126something more complicated in reality (such as adding ``spam'' to
127every command). This function <tt class="cfunction">PySpam_System()</tt> is also
128exported to other extension modules.
129
130<P>
131The function <tt class="cfunction">PySpam_System()</tt> is a plain C function,
132declared <tt class="keyword">static</tt> like everything else:
133
134<P>
135<div class="verbatim"><pre>
136static int
137PySpam_System(const char *command)
138{
139 return system(command);
140}
141</pre></div>
142
143<P>
144The function <tt class="cfunction">spam_system()</tt> is modified in a trivial way:
145
146<P>
147<div class="verbatim"><pre>
148static PyObject *
149spam_system(PyObject *self, PyObject *args)
150{
151 const char *command;
152 int sts;
153
154 if (!PyArg_ParseTuple(args, "s", &amp;command))
155 return NULL;
156 sts = PySpam_System(command);
157 return Py_BuildValue("i", sts);
158}
159</pre></div>
160
161<P>
162In the beginning of the module, right after the line
163
164<P>
165<div class="verbatim"><pre>
166#include "Python.h"
167</pre></div>
168
169<P>
170two more lines must be added:
171
172<P>
173<div class="verbatim"><pre>
174#define SPAM_MODULE
175#include "spammodule.h"
176</pre></div>
177
178<P>
179The <code>#define</code> is used to tell the header file that it is being
180included in the exporting module, not a client module. Finally,
181the module's initialization function must take care of initializing
182the C API pointer array:
183
184<P>
185<div class="verbatim"><pre>
186PyMODINIT_FUNC
187initspam(void)
188{
189 PyObject *m;
190 static void *PySpam_API[PySpam_API_pointers];
191 PyObject *c_api_object;
192
193 m = Py_InitModule("spam", SpamMethods);
194
195 /* Initialize the C API pointer array */
196 PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;
197
198 /* Create a CObject containing the API pointer array's address */
199 c_api_object = PyCObject_FromVoidPtr((void *)PySpam_API, NULL);
200
201 if (c_api_object != NULL)
202 PyModule_AddObject(m, "_C_API", c_api_object);
203}
204</pre></div>
205
206<P>
207Note that <code>PySpam_API</code> is declared <tt class="keyword">static</tt>; otherwise
208the pointer array would disappear when <tt class="function">initspam()</tt> terminates!
209
210<P>
211The bulk of the work is in the header file <span class="file">spammodule.h</span>,
212which looks like this:
213
214<P>
215<div class="verbatim"><pre>
216#ifndef Py_SPAMMODULE_H
217#define Py_SPAMMODULE_H
218#ifdef __cplusplus
219extern "C" {
220#endif
221
222/* Header file for spammodule */
223
224/* C API functions */
225#define PySpam_System_NUM 0
226#define PySpam_System_RETURN int
227#define PySpam_System_PROTO (const char *command)
228
229/* Total number of C API pointers */
230#define PySpam_API_pointers 1
231
232
233#ifdef SPAM_MODULE
234/* This section is used when compiling spammodule.c */
235
236static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;
237
238#else
239/* This section is used in modules that use spammodule's API */
240
241static void **PySpam_API;
242
243#define PySpam_System \
244 (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])
245
246/* Return -1 and set exception on error, 0 on success. */
247static int
248import_spam(void)
249{
250 PyObject *module = PyImport_ImportModule("spam");
251
252 if (module != NULL) {
253 PyObject *c_api_object = PyObject_GetAttrString(module, "_C_API");
254 if (c_api_object == NULL)
255 return -1;
256 if (PyCObject_Check(c_api_object))
257 PySpam_API = (void **)PyCObject_AsVoidPtr(c_api_object);
258 Py_DECREF(c_api_object);
259 }
260 return 0;
261}
262
263#endif
264
265#ifdef __cplusplus
266}
267#endif
268
269#endif /* !defined(Py_SPAMMODULE_H) */
270</pre></div>
271
272<P>
273All that a client module must do in order to have access to the
274function <tt class="cfunction">PySpam_System()</tt> is to call the function (or
275rather macro) <tt class="cfunction">import_spam()</tt> in its initialization
276function:
277
278<P>
279<div class="verbatim"><pre>
280PyMODINIT_FUNC
281initclient(void)
282{
283 PyObject *m;
284
285 Py_InitModule("client", ClientMethods);
286 if (import_spam() &lt; 0)
287 return;
288 /* additional initialization can happen here */
289}
290</pre></div>
291
292<P>
293The main disadvantage of this approach is that the file
294<span class="file">spammodule.h</span> is rather complicated. However, the
295basic structure is the same for each function that is
296exported, so it has to be learned only once.
297
298<P>
299Finally it should be mentioned that CObjects offer additional
300functionality, which is especially useful for memory allocation and
301deallocation of the pointer stored in a CObject. The details
302are described in the <em class="citetitle"><a
303 href="../api/api.html"
304 title="Python/C API
305Reference Manual"
306 >Python/C API
307Reference Manual</a></em> in the section
308``<a class="ulink" href="../api/cObjects.html"
309 >CObjects</a>'' and in the implementation
310of CObjects (files <span class="file">Include/cobject.h</span> and
311<span class="file">Objects/cobject.c</span> in the Python source code distribution).
312
313<DIV CLASS="navigation">
314<div class='online-navigation'>
315<p></p><hr />
316<table align="center" width="100%" cellpadding="0" cellspacing="2">
317<tr>
318<td class='online-navigation'><a rel="prev" title="1.11 Writing Extensions in"
319 href="cplusplus.html"><img src='../icons/previous.png'
320 border='0' height='32' alt='Previous Page' width='32' /></A></td>
321<td class='online-navigation'><a rel="parent" title="1. Extending Python with"
322 href="intro.html"><img src='../icons/up.png'
323 border='0' height='32' alt='Up One Level' width='32' /></A></td>
324<td class='online-navigation'><a rel="next" title="2. Defining New Types"
325 href="defining-new-types.html"><img src='../icons/next.png'
326 border='0' height='32' alt='Next Page' width='32' /></A></td>
327<td align="center" width="100%">Extending and Embedding the Python Interpreter</td>
328<td class='online-navigation'><a rel="contents" title="Table of Contents"
329 href="contents.html"><img src='../icons/contents.png'
330 border='0' height='32' alt='Contents' width='32' /></A></td>
331<td class='online-navigation'><img src='../icons/blank.png'
332 border='0' height='32' alt='' width='32' /></td>
333<td class='online-navigation'><img src='../icons/blank.png'
334 border='0' height='32' alt='' width='32' /></td>
335</tr></table>
336<div class='online-navigation'>
337<b class="navlabel">Previous:</b>
338<a class="sectref" rel="prev" href="cplusplus.html">1.11 Writing Extensions in</A>
339<b class="navlabel">Up:</b>
340<a class="sectref" rel="parent" href="intro.html">1. Extending Python with</A>
341<b class="navlabel">Next:</b>
342<a class="sectref" rel="next" href="defining-new-types.html">2. Defining New Types</A>
343</div>
344</div>
345<hr />
346<span class="release-info">Release 2.4.2, documentation updated on 28 September 2005.</span>
347</DIV>
348<!--End of Navigation Panel-->
349<ADDRESS>
350See <i><a href="about.html">About this document...</a></i> for information on suggesting changes.
351</ADDRESS>
352</BODY>
353</HTML>