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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 874 - (hide annotations) (download) (as text)
Thu Oct 5 15:13:22 2006 UTC (14 years ago) by johnpye
File MIME type: text/x-csrc
File size: 7433 byte(s)
Can now access python methods from ASCEND. Still can't access the 'SELF' instance: that's the next thing to do.
1 johnpye 862 /* 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 johnpye 869 *//**
19     @file
20     Import handler to provide external python script functionality for ASCEND.
21 johnpye 862 */
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 johnpye 873 #include <compiler/extfunc.h>
32 johnpye 862
33 johnpye 865 #include <Python.h>
34    
35 johnpye 862 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 johnpye 873 CONSOLE_DEBUG("Hello...");
51 johnpye 862
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 johnpye 869 /*------------------------------------------------------------------------------
68 johnpye 873 PYTHON METHOD INVOKER
69 johnpye 869 */
70    
71 johnpye 873 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 johnpye 874 PyObject *fn, *arglist, *result;
83 johnpye 873 /* cast user data to PyObject pointer */
84 johnpye 874
85     CONSOLE_DEBUG("USER_DATA IS AT %p",user_data);
86    
87 johnpye 873 fn = (PyObject *) user_data;
88    
89     ERROR_REPORTER_HERE(ASC_USER_NOTE,"RUNNING PYTHON METHOD");
90     CONSOLE_DEBUG("RUNNING PYTHON METHOD...");
91 johnpye 874
92     PyErr_Clear();
93    
94     if(!PyCallable_Check(fn)){
95     ERROR_REPORTER_HERE(ASC_PROG_ERR,"user_data is not a PyCallable");
96     return 1;
97     }
98    
99     arglist = Py_BuildValue("(i)", 666);
100     result = PyEval_CallObject(fn, arglist);
101     Py_DECREF(arglist);
102     if(PyErr_Occurred()){
103     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed running python method");
104     return 1;
105     }
106    
107     return 0;
108 johnpye 873 }
109    
110     /*------------------------------------------------------------------------------
111     'EXTPY' PYTHON STATIC MODULE
112     */
113    
114 johnpye 869 static PyObject *extpy_getbrowser(PyObject *self, PyObject *args){
115     PyObject *browser;
116     if(args!=NULL){
117     ERROR_REPORTER_HERE(ASC_PROG_ERR,"args is not NULL?!");
118     }
119     browser = (PyObject *)importhandler_getsharedpointer("browser");
120     return Py_BuildValue("O",browser);
121     }
122    
123 johnpye 873 static PyObject *extpy_registermethod(PyObject *self, PyObject *args){
124     PyObject *fn, *name, *docstring;
125     const char *cname, *cdocstring;
126     int res;
127     int nargs = 1;
128    
129     PyArg_ParseTuple(args,"O:registermethod", &fn);
130     if(!PyCallable_Check(fn)){
131     PyErr_SetString(PyExc_TypeError,"parameter must be callable");
132     return NULL;
133     }
134    
135     CONSOLE_DEBUG("FOUND FN=%p",fn);
136    
137     name = PyObject_GetAttr(fn,PyString_FromString("__name__"));
138     if(name==NULL){
139     CONSOLE_DEBUG("No __name__ attribute");
140     PyErr_SetString(PyExc_TypeError,"No __name__ attribute");
141     return NULL;
142     }
143     cname = PyString_AsString(name);
144    
145     CONSOLE_DEBUG("REGISTERED METHOD '%s' HAS %d ARGS",cname,nargs);
146    
147     docstring = PyObject_GetAttr(fn,PyString_FromString("func_doc"));
148     cdocstring = "(no help)";
149     if(name!=NULL){
150     cdocstring = PyString_AsString(docstring);
151     CONSOLE_DEBUG("DOCSTRING: %s",cdocstring);
152     }
153    
154 johnpye 874 res = CreateUserFunctionMethod(cname,extpy_invokemethod,nargs,cdocstring,(void *)fn);
155     CONSOLE_DEBUG("PYTHON FUNCTION IS AT %p",fn);
156     Py_INCREF(fn);
157     CONSOLE_DEBUG("PYTHON FUNCTION IS AT %p",fn);
158 johnpye 873
159     CONSOLE_DEBUG("EXTPY INVOKER IS AT %p",extpy_invokemethod);
160    
161     if(res){
162     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Problem registering external script method (%d)",res);
163     PyErr_SetString(PyExc_Exception,"unable to register script method");
164     return NULL;
165     }
166    
167     ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Registered python method '%s'",cname);
168    
169     /* nothing gets returned (but possibly an exception) */
170     Py_INCREF(Py_None);
171     return Py_None;
172     }
173    
174 johnpye 869 static PyMethodDef extpymethods[] = {
175     {"getbrowser", extpy_getbrowser, METH_NOARGS,"Retrieve browser pointer"}
176 johnpye 873 ,{"registermethod", extpy_registermethod, METH_VARARGS,"Register a python method as an ASCEND script method"}
177 johnpye 869 ,{NULL,NULL,0,NULL}
178     };
179    
180     PyMODINIT_FUNC initextpy(void){
181     PyObject *obj;
182     obj = Py_InitModule3("extpy", extpymethods,"Module for accessing shared ASCEND pointers from python");
183     }
184    
185     /*------------------------------------------------------------------------------
186     STANDARD IMPORT HANDLER ROUTINES
187     */
188    
189 johnpye 862 /**
190     Create a filename base on a partial filename. In that case of python, this
191     just means adding '.py' to the end.
192 johnpye 867
193 johnpye 862 @param partialname the filename without suffix, as specified in the user's "IMPORT" command
194     @return new filename, or NULL on failure
195     */
196     char *extpy_filename(const char *partialname){
197     char *name;
198     int len;
199     if(partialname==NULL){
200     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Partial name is NULL, can't work out filename");
201     return NULL;
202     }
203 johnpye 867
204 johnpye 862 len = strlen(partialname);
205     name = ASC_NEW_ARRAY_CLEAR(char,len+4);
206     strcpy(name,partialname);
207     strcat(name,".py");
208 johnpye 865 CONSOLE_DEBUG("New filename is '%s'",name);
209 johnpye 862 return name;
210     }
211    
212     /**
213     Import a python script located at the path indicated.
214    
215     @return 0 on success, else error codes (TBD)
216     */
217 johnpye 864 int extpy_import(const struct FilePath *fp, const char *initfunc, const char *partialpath){
218 johnpye 862 char *name;
219     name = ospath_str(fp);
220 johnpye 865 FILE *f;
221 johnpye 872 PyObject *pyfile;
222 johnpye 865
223 johnpye 873 CONSOLE_DEBUG("Importing Python script %s",name);
224 johnpye 865 if(Py_IsInitialized()){
225 johnpye 873 CONSOLE_DEBUG("Python was already initialised");
226 johnpye 865 }else{
227     CONSOLE_DEBUG("INITIALISING PYTHON");
228     Py_Initialize();
229 johnpye 867 CONSOLE_DEBUG("COMPLETED ATTEMPT TO INITIALISE PYTHON");
230 johnpye 865 }
231    
232 johnpye 867 if(!Py_IsInitialized()){
233 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to initialise Python");
234 johnpye 867 CONSOLE_DEBUG("UNABLE TO INITIALIZE PYTHON");
235 johnpye 873 ASC_FREE(name);
236 johnpye 867 return 1;
237     }
238    
239 johnpye 869 initextpy();
240    
241 johnpye 872 pyfile = PyFile_FromString(name,"r");
242     if(pyfile==NULL){
243 johnpye 871 CONSOLE_DEBUG("Failed opening script");
244 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to open '%s' (%s)",partialpath,name);
245     ASC_FREE(name);
246 johnpye 871 return 1;
247     }
248 johnpye 872
249     f = PyFile_AsFile(pyfile);
250     if(f==NULL){
251 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to cast PyObject to FILE*");
252     ASC_FREE(name);
253 johnpye 872 return 1;
254     }
255 johnpye 873
256 johnpye 872 PyRun_AnyFileEx(f,name,1);
257 johnpye 873 /*if(PyErr_Occurred()){
258     ERROR_REPORTER_HERE(ASC_PROG_ERR,"An error occurred in the python script '%s'. Check the console for details");
259     PyErr_Print();
260     PyErr_Clear();
261     return 1;
262     }*/
263 johnpye 871
264 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Imported python script '%s' (check console for errors)",partialpath);
265    
266 johnpye 862 ASC_FREE(name);
267 johnpye 873 return 0;
268 johnpye 862 }
269    

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