summaryrefslogtreecommitdiffstats
path: root/doc/libpythonize.html
blob: 0aae9a200cd9a6ce94dd1456275288851d5a5211 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Pythonize class and libpythonize</title>
</head>
<body>
<div class="NAVHEADER">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<TR>
<TH COLSPAN="3" ALIGN="center">Python Bindings for KDE (PyKDE-3.16.0)</TH>
</TR>
<tr>
<td width="33%" align="left" valign="bottom">
<a href="panapp5.html" accesskey="P" >Prev</a>
</td>
<td width="34%" align="center" valign="bottom"></td>
<td width="33%" align="right" valign="bottom"></td>
</tr>
</table>
</div>
<hr align="LEFT"  width="100%">
<div align="center"><h1>Pythonize Class and libpythonize</h1></div>
<p>
libPythonize and the Pythonize class simplify embedding, loading and communicating with the Python
interpreter. Pythonize is a class with methods for handling the interpreter and is included in libpythonize.
Also in libpythonize is a C wrapper for the C++ Pythonize class. There is also a standalone C library
libpythonizec, written completely in C. All 3 versions (C++, C and C wrapper) use the same methods/functions
and the same args - the only major difference is in initialization and finalization.
</p>
<p>
The method descriptions here apply to both C and C++ versions unless noted.
</p>
<p>
Although libpythonize is used with (and installed with) PyKDE, it has no dependencies itself on
PyKDE/KDE, PyTQt/TQt or sip. It does require qmake from TrollTech (part of TQt) to build.
</p>

<h2>Initialization and Finalization</h2>
In C++, the interpreter is loaded and initialized using the Pythonize () constructor, which takes 
no arguments. In C, the initialize() function call accomplishes the same thing.

The interpreter is finalized in C++ using the destructor  ~Pythonize (). In C, the finalize() function
accomplishes the same thing.

<h2>Threading and Locking</h2>
<p>
Pythonize obtains the Python global interpreter lock when it initializes Python. It is currently the
programmer's responsibility to release the lock when C++ accesses to the interpreter are complete. If
the lock is not released, access will be denied to Python code relying on the interpreter (for example
bindings like PyTQt or PyKDE).
</p>
<p>
If a second instance of Pythonize is created (within the same parent process), that instance will actquire
the lock automatically. In order to allow a second (and third or more) instance of Pythonize to be
created and obtain the lock, it's necessary to have a related thread state (PyThreadState). This thread
state is created by a call to PyThreadState_Get when the first instance of Pythonize is created. The
thread state is stored in a global variable (declared in the cpp file) that is used by all subsequent
instances of Pythonize. This means that applications using libpythonize are mormally single-threaded,
at least in relation to the libpythonize interpreter instance. This is important for utilization with
sip-based bindings like PyKDE and PyTQt.
</p>
<p>
The global thread state is accessible via the getThreadState/setThreadState methods.
</p>
<h2>Methods/Functions</h2>
<p>
Methods are either called directly in C or as class members in C++. In C, int variables/values are
used instead of bool.
</p>
<table border="0" bgcolor="#E0E0E0" width="100%">
<tr>
<td>
<pre CLASS="PROGRAMLISTING"> 
C++:
	Pythonize *pyize = Pythonize ();
	...
	bool result = pyize->appendToSysPath ("/usr/local/foo");

C:
	initialize ();
	...
	int result = appendToSysPath ("/usr/local/foo");
</pre>
</td>
</tr>
</table>
<hr>
<h3>Pythonize () [C++] or initialize () [C]</h3>
<p>
Constructor/initializer - loads and initializaes the interpreter and actquires the global interpreter lock.
Sets the value of pythonInit to <b>true</b> on success or <b>false</b> if construction/initialization fails
Initializes the global thread state (first instance) or restores the global thread state (second and later
instances). It is the programmer's resposibility to release the global interpreter lock to enable other
code to access the interpreter. The lock and thread state are automatically actquired when any Pythonize
instance is created..
</p>
<hr>
<h3>bool  getPythonInit ()</h3>
<p>
Returns the result of initializing/constructing the interpreter object. If the
return value is <strong>true</strong>, the interpreter should be usable.
If it returns <strong>false</strong>, an error occurred and the interpreter
will not be useful. Most methods/functions check the value of pythonInit
and won't run if it's <strong>false</strong>
</p>
<hr>
<h3>~Pythonize () [C++] or finalize () [C]</h3>
<p>
Destructor/finalizer - shuts down the interpreter and destroys the class Sets pythonInit to <b>false</b>.
</p>
<hr>
<h3>bool appendToSysPath (const char* newPath);</h3>
<p>
Appends newPath to sys.path
</p>
<hr>
<h3>PyObject  *importModule (char *moduleName);</h3>
<p>
Imports a module into the interpreter. Same as "import <moduleName>" in Python. moduleName
must exist somewhere on sys.path. Returns a reference to the module imported. Returns <b>NULL</b> on failure.
</p>
<hr>
<h3>PyObject  *getNewObjectRef (PyObject *module, char *object)</h3>
<p>
Returns a reference to an object in an already loaded module (use importModule to load
the module or get a reference to it) Returns <b>NULL</b> on failure.
</p>
<hr>
<h3>PyObject  *getSysModule ()</h3>
<p>
Returns a reference to the Python sys module. Returns <b>NULL</b> on failure.
</p>
<hr>
<h3>PyObject  *getMainModule ()</h3>
<p>
Returns a reference to the Python main module. Returns <b>NULL</b> on failure.
</p>
<hr>
<h3>[internal] void *setMainModule ()</h3>
<p>
Sets internal value of main module
</p>
<hr>
<h3>void  decref (PyObject *object)</h3>
<p>
Uses Py_XDECREF to decrement the reference count of an object
</p>
<hr>
<h3>bool  runScript (char *scriptPath);</h3>
<p>
Runs an arbitrary script in the interpreter and returns Python's result.
</p>
<hr>
<h3>bool  runString (char *str);</h3>
<p>
Runs an arbitrary string in the interpreter (indentation required for mulit-line
strings) and returns Python's result.
</p>
<hr>
<h3>PyObject  *runFunction (PyObject *object, PyObject *args);</h3>
<p>
If <em>object</em> is callable, runs <em>object</em> with <em>args</em> and
returns the results of the function call as a PyObject. Returns <b>NULL</b> on failure.
</p>
<hr>
<h3>void  releaseLock ()</h3>
<p>
Releases the global interpreter lock using PyEval_SaveThread. Saves the global thread state.
</p>
<hr>
<h3>void  actquireLock ()</h3>
<p>
Actquires the global interpreter lock using PyEval_RestoreThread. Restores the global thread state.
</p>
<hr>
<h3>PyThreadState *getThreadState ()</h3>
<p>
Retrieves the current value of the global thread state. Does not affect the global interpreter lock.
</p>
<hr>
<h3>PyThreadState  *setThreadState (PyThreadState *tstate)</h3>
<p>
Sets the global thread state to <i>tstate</i> and returns the previous global thread state. Does
not affect the global interpreter lock.
</p>
<hr>
<h2>Using libpythonize in an application</h2>
<p>
Include the pythonize.h header file (requires Python.h) and link to libpythonize.so - that's pretty much it. There are unit tests
in both C and C++ in the pythonize/tests/ subdirectory. An example of libpythonize usage is in pykpanelapplet.cpp in the
PyKDE distribution (pykpanelapplet/ directory).
</p>
<h2>Obtaining and building libpythonize</h2>
<p>
At present only the C++/C wrapper versions are available, and they're distributed with PyKDE.
</p>
<p>
The build process for libpythonize uses TrollTech's qmake (available as part of TQt), but is simple enough
to be included in most make files. See the pythonize.pro file for more information - most of the additional
libs required are required by libpython, and may vary by platform.
</p>
<p>
You can contact me at  this address: <a href="mailto:[email protected]">Jim Bublitz &lt;[email protected]&gt;</a>
</p>
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="33%" align="left" valign="top">
<a href="panapp5.html" accesskey="P" >Prev</a>
</td>
<td width="34%" align="center" valign="top">
<a href="index.html" accesskey="H">Home</a>
</td>
<td width="33%" align="right" valign="top"></td>
</tr>
<tr>
<td width="33%" align="left" valign="top">Applet Installer</td>
<td width="34%" align="center" valign="top">&nbsp;</td>
<td width="33%" align="right" valign="top"></td>
</tr>
</table>
</div>
</body>
</html>