1 /* copyright 2003 Jim Bublitz <jbublitz@nwinternet.com>
2 
3    This library is free software; you can redistribute it and/or
4    modify it under the terms of the GNU Library General Public
5    License as published by the Free Software Foundation; either
6    version 2 of the License, or (at your option) any later version.
7 
8    This library is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    Library General Public License for more details.
12 
13    You should have received a copy of the GNU Library General Public License
14    along with this library; see the file COPYING.LIB.  If not, write to
15    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16    Boston, MA 02110-1301, USA.
17 */
18 
19 #include <stdarg.h>
20 #include <string.h>
21 
22 // this just gets rid of a warning when Python.h redefines it
23 #undef _POSIX_C_SOURCE
24 
25 #include <pythonize.h>
26 
27 #define debug 1
28 
ObjectRef(ObjectRef * oi,PyObject * o)29 ObjectRef::ObjectRef (ObjectRef *oi, PyObject *o)
30 {
31     prevObject = oi;
32     object     = o;
33 }
34 
35 
Pythonize()36 Pythonize::Pythonize ()
37 {
38     pythonInit  = 1;
39 	objects    = nullptr;
40 
41     if (debug) printf ("\n\nPythonize constructor -- pid = %i\n", getpid ());
42 
43     if (!Py_IsInitialized ())
44     {
45         PyEval_InitThreads ();
46         Py_Initialize ();
47         if (!Py_IsInitialized ())
48         {
49             pythonInit = 0;
50             return;
51         }
52 
53         if (debug) printf ("Python interpreter initialized!\n\n");
54 
55         // free the lock
56         PyEval_ReleaseLock();
57     }
58 }
59 
runScript(char * scriptPath)60 bool Pythonize::runScript (char *scriptPath)
61 {
62     FILE *f;
63     int res;
64 
65     if (debug) printf ("Running script: %s\n", scriptPath);
66 
67 	if (scriptPath == nullptr || strlen (scriptPath) == 0) return false;
68 
69     f = fopen (scriptPath, "r");
70 	if (f == nullptr) return false;
71 
72     res = PyRun_SimpleFile (f, scriptPath);
73 
74     fclose (f);
75     return res == 0;
76 }
77 
78 
runFunction(PyObject * object,PyObject * args)79 PyObject * Pythonize::runFunction (PyObject *object, PyObject *args)
80 {
81 
82     if (!PyCallable_Check (object))
83 		return nullptr;
84 
85     PyObject *res = PyObject_CallObject (object, args ? args : PyTuple_New (0));
86     Py_XINCREF (res);
87 
88     return res;
89 }
90 
runFunctionVoid(PyObject * object,PyObject * args)91 void * Pythonize::runFunctionVoid (PyObject *object, PyObject *args)
92 {
93 
94     if (!PyCallable_Check (object))
95 		return nullptr;
96 
97     PyObject *pyRes = PyObject_CallObject (object, args ? args : PyTuple_New (0));
98     void *res = PyLong_AsVoidPtr (pyRes);
99 
100     return res;
101 }
102 
runString(char * str)103 bool Pythonize::runString (char *str)
104 {
105 	if (str == nullptr || strlen (str) == 0) return false;
106 
107     int res = PyRun_SimpleString (str);
108 
109     return res == 0;
110 }
111 
appendToSysPath(const char * newPath)112 bool Pythonize::appendToSysPath (const char* newPath)
113 {
114 	if (newPath == nullptr || strlen (newPath) == 0) return false;
115 
116     char *fmtString = "import sys\nif not '%s' in sys.path:\n\tsys.path.append ('%s')\n"; //print sys.path\n";
117     int length      = strlen (fmtString) + 2*strlen (newPath) + 1;
118     char *line      = new char [length];
119     if (!line) return false;
120     snprintf (line, length, fmtString, newPath, newPath);
121 
122     int res = PyRun_SimpleString (line);
123 
124     delete[] line;
125     return res == 0;
126 }
127 
importModule(char * moduleName)128 PyObject *Pythonize::importModule (char *moduleName)
129 {
130 	if (moduleName == nullptr || strlen (moduleName) == 0) return nullptr;
131 
132     PyObject *module = PyImport_ImportModule (moduleName);
133 
134     objects = new ObjectRef (objects, module);
135 	if (!objects) return nullptr;
136 
137     return module;
138 }
139 
140 
~Pythonize()141 Pythonize::~Pythonize ()
142 {
143 
144     if (debug) printf ("Pythonize destructor\n");
145     ObjectRef *top;
146 
147     while (objects)
148     {
149         top = objects;
150         objects = objects->prevObject;
151         delete top;
152     }
153     if (debug) printf (" --- Objects destroyed\n");
154 
155     Py_Finalize();
156 
157     if (debug) printf (" --- Py_Finalized\n");
158 }
159 
160 //// XXX: disabled
161 //// The global Pythonize instance
162 //Pythonize *pyize = new Pythonize ();
163 
164 extern "C"
165 {
166     Pythonize *_pythonize;
167 
initialize()168     Pythonize *initialize ()
169     {
170         if (_pythonize) return _pythonize;
171 
172         _pythonize = new Pythonize ();
173         if (!_pythonize || !_pythonize->getPythonInit ())
174         {
175             if (_pythonize) delete _pythonize;
176 			return nullptr;
177         }
178 
179         return _pythonize;
180     }
181 
finalize()182     void finalize ()
183     {
184         if (_pythonize) {
185             if (debug) printf(" --- Pythonize finalize()\n");
186             delete _pythonize;
187         }
188     }
189 
190     // adds a path to sys.path
appendToSysPath(const char * newPath)191     bool appendToSysPath (const char* newPath)
192     {
193         return _pythonize ? _pythonize->appendToSysPath (newPath) : false;
194     }
195 
196     // imports a module into the interpreter
197     // or gets a PyObject for an already loaded module
importModule(char * moduleName)198     PyObject *importModule (char *moduleName)
199     {
200 		return _pythonize ? _pythonize->importModule (moduleName) : nullptr;
201     }
202 
203     // returns an object from a loaded module
204     // you must decref the object returned when done with it (new reference returned)
getNewObjectRef(PyObject * module,char * object)205     PyObject *getNewObjectRef (PyObject *module, char *object)
206     {
207 		return _pythonize ? _pythonize->getNewObjectRef (module, object) : nullptr;
208     }
209 
getPythonInit()210     bool getPythonInit ()
211     {
212         return _pythonize ? _pythonize->getPythonInit () : false;
213     }
214 
215     // decrements the ref count of an object
decref(PyObject * object)216     void decref (PyObject *object)
217     {
218         Py_XDECREF (object);
219     }
220 
221     // runs a script on the current sys.path
runScript(char * scriptPath)222     bool runScript (char *scriptPath)
223     {
224         return _pythonize ? _pythonize->runScript (scriptPath) : false;
225     }
226 
227     // executes a string of Python in the interpreter
runString(char * str)228     bool runString (char *str)
229     {
230         return _pythonize ? _pythonize->runString (str) : false;
231     }
232 
233     // runs a callable Python object
runFunction(PyObject * object,PyObject * args)234     PyObject *runFunction (PyObject *object, PyObject *args)
235     {
236 		return _pythonize ? _pythonize->runFunction (object, args) : nullptr;
237     }
238 }
239