/[ascend]/trunk/models/johnpye/extpy/extpy.c
ViewVC logotype

Contents of /trunk/models/johnpye/extpy/extpy.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 873 - (show annotations) (download) (as text)
Thu Oct 5 14:51:49 2006 UTC (14 years ago) by johnpye
File MIME type: text/x-csrc
File size: 6923 byte(s)
Can now register python methods with ASCEND. Still can't execute the python code, but getting close.
1 /* ASCEND modelling environment
2 Copyright (C) 2006 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//**
19 @file
20 Import handler to provide external python script functionality for ASCEND.
21 */
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include <utilities/ascConfig.h>
27 #include <utilities/error.h>
28 #include <general/ospath.h>
29
30 #include <compiler/importhandler.h>
31 #include <compiler/extfunc.h>
32
33 #include <Python.h>
34
35 ImportHandlerCreateFilenameFn extpy_filename;
36 ImportHandlerImportFn extpy_import;
37
38 #ifndef ASC_EXPORT
39 # error "Where is ASC_EXPORT?"
40 #endif
41
42 /**
43 This is the function called from "IMPORT extpy"
44
45 It sets up the functions in this external function library
46 */
47 extern ASC_EXPORT(int) extpy_register(){
48 int result = 0;
49
50 CONSOLE_DEBUG("Hello...");
51
52 struct ImportHandler *handler;
53 handler = ASC_NEW(struct ImportHandler);
54
55 handler->name = "extpy";
56 handler->filenamefn = extpy_filename;
57 handler->importfn = extpy_import;
58
59 result = importhandler_add(handler);
60
61 if(result){
62 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to register import handler (error = %d)",result);
63 }
64 return result;
65 }
66
67 /*------------------------------------------------------------------------------
68 PYTHON METHOD INVOKER
69 */
70
71 ExtMethodRun extpy_invokemethod;
72
73 /** Method invoker. extpy will supply a pointer to this function whenever it
74 registers a python function as an external script method. This function will
75 then dereference the user_data field into a python function, and execute that
76 python function.
77
78 One difficult aspect is the question of how to usefully pass the 'context'
79 argument to Python?
80 */
81 int extpy_invokemethod(struct Instance *context, struct gl_list_t *args, void *user_data){
82 PyObject *fn;
83 /* cast user data to PyObject pointer */
84 fn = (PyObject *) user_data;
85
86 ERROR_REPORTER_HERE(ASC_USER_NOTE,"RUNNING PYTHON METHOD");
87 CONSOLE_DEBUG("RUNNING PYTHON METHOD...");
88 return 1;
89 }
90
91 /*------------------------------------------------------------------------------
92 'EXTPY' PYTHON STATIC MODULE
93 */
94
95 static PyObject *extpy_getbrowser(PyObject *self, PyObject *args){
96 PyObject *browser;
97 if(args!=NULL){
98 ERROR_REPORTER_HERE(ASC_PROG_ERR,"args is not NULL?!");
99 }
100 browser = (PyObject *)importhandler_getsharedpointer("browser");
101 return Py_BuildValue("O",browser);
102 }
103
104 static PyObject *extpy_registermethod(PyObject *self, PyObject *args){
105 PyObject *fn, *name, *docstring;
106 const char *cname, *cdocstring;
107 int res;
108 int nargs = 1;
109
110 PyArg_ParseTuple(args,"O:registermethod", &fn);
111 if(!PyCallable_Check(fn)){
112 PyErr_SetString(PyExc_TypeError,"parameter must be callable");
113 return NULL;
114 }
115 Py_INCREF(fn);
116
117 CONSOLE_DEBUG("FOUND FN=%p",fn);
118
119 name = PyObject_GetAttr(fn,PyString_FromString("__name__"));
120 if(name==NULL){
121 CONSOLE_DEBUG("No __name__ attribute");
122 PyErr_SetString(PyExc_TypeError,"No __name__ attribute");
123 return NULL;
124 }
125 cname = PyString_AsString(name);
126
127 CONSOLE_DEBUG("REGISTERED METHOD '%s' HAS %d ARGS",cname,nargs);
128
129 docstring = PyObject_GetAttr(fn,PyString_FromString("func_doc"));
130 cdocstring = "(no help)";
131 if(name!=NULL){
132 cdocstring = PyString_AsString(docstring);
133 CONSOLE_DEBUG("DOCSTRING: %s",cdocstring);
134 }
135
136 res = CreateUserFunctionMethod(cname,extpy_invokemethod,nargs,cdocstring,fn);
137
138 CONSOLE_DEBUG("EXTPY INVOKER IS AT %p",extpy_invokemethod);
139
140 if(res){
141 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem registering external script method (%d)",res);
142 PyErr_SetString(PyExc_Exception,"unable to register script method");
143 return NULL;
144 }
145
146 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Registered python method '%s'",cname);
147
148 /* nothing gets returned (but possibly an exception) */
149 Py_INCREF(Py_None);
150 return Py_None;
151 }
152
153 static PyMethodDef extpymethods[] = {
154 {"getbrowser", extpy_getbrowser, METH_NOARGS,"Retrieve browser pointer"}
155 ,{"registermethod", extpy_registermethod, METH_VARARGS,"Register a python method as an ASCEND script method"}
156 ,{NULL,NULL,0,NULL}
157 };
158
159 PyMODINIT_FUNC initextpy(void){
160 PyObject *obj;
161 obj = Py_InitModule3("extpy", extpymethods,"Module for accessing shared ASCEND pointers from python");
162 }
163
164 /*------------------------------------------------------------------------------
165 STANDARD IMPORT HANDLER ROUTINES
166 */
167
168 /**
169 Create a filename base on a partial filename. In that case of python, this
170 just means adding '.py' to the end.
171
172 @param partialname the filename without suffix, as specified in the user's "IMPORT" command
173 @return new filename, or NULL on failure
174 */
175 char *extpy_filename(const char *partialname){
176 char *name;
177 int len;
178 if(partialname==NULL){
179 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Partial name is NULL, can't work out filename");
180 return NULL;
181 }
182
183 len = strlen(partialname);
184 name = ASC_NEW_ARRAY_CLEAR(char,len+4);
185 strcpy(name,partialname);
186 strcat(name,".py");
187 CONSOLE_DEBUG("New filename is '%s'",name);
188 return name;
189 }
190
191 /**
192 Import a python script located at the path indicated.
193
194 @return 0 on success, else error codes (TBD)
195 */
196 int extpy_import(const struct FilePath *fp, const char *initfunc, const char *partialpath){
197 char *name;
198 name = ospath_str(fp);
199 FILE *f;
200 PyObject *pyfile;
201
202 CONSOLE_DEBUG("Importing Python script %s",name);
203 if(Py_IsInitialized()){
204 CONSOLE_DEBUG("Python was already initialised");
205 }else{
206 CONSOLE_DEBUG("INITIALISING PYTHON");
207 Py_Initialize();
208 CONSOLE_DEBUG("COMPLETED ATTEMPT TO INITIALISE PYTHON");
209 }
210
211 if(!Py_IsInitialized()){
212 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to initialise Python");
213 CONSOLE_DEBUG("UNABLE TO INITIALIZE PYTHON");
214 ASC_FREE(name);
215 return 1;
216 }
217
218 initextpy();
219
220 pyfile = PyFile_FromString(name,"r");
221 if(pyfile==NULL){
222 CONSOLE_DEBUG("Failed opening script");
223 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to open '%s' (%s)",partialpath,name);
224 ASC_FREE(name);
225 return 1;
226 }
227
228 f = PyFile_AsFile(pyfile);
229 if(f==NULL){
230 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to cast PyObject to FILE*");
231 ASC_FREE(name);
232 return 1;
233 }
234
235 PyRun_AnyFileEx(f,name,1);
236 /*if(PyErr_Occurred()){
237 ERROR_REPORTER_HERE(ASC_PROG_ERR,"An error occurred in the python script '%s'. Check the console for details");
238 PyErr_Print();
239 PyErr_Clear();
240 return 1;
241 }*/
242
243 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Imported python script '%s' (check console for errors)",partialpath);
244
245 ASC_FREE(name);
246 return 0;
247 }
248

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22