/[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 873 - (hide 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 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     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 johnpye 869 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 johnpye 873 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 johnpye 869 static PyMethodDef extpymethods[] = {
154     {"getbrowser", extpy_getbrowser, METH_NOARGS,"Retrieve browser pointer"}
155 johnpye 873 ,{"registermethod", extpy_registermethod, METH_VARARGS,"Register a python method as an ASCEND script method"}
156 johnpye 869 ,{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 johnpye 862 /**
169     Create a filename base on a partial filename. In that case of python, this
170     just means adding '.py' to the end.
171 johnpye 867
172 johnpye 862 @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 johnpye 867
183 johnpye 862 len = strlen(partialname);
184     name = ASC_NEW_ARRAY_CLEAR(char,len+4);
185     strcpy(name,partialname);
186     strcat(name,".py");
187 johnpye 865 CONSOLE_DEBUG("New filename is '%s'",name);
188 johnpye 862 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 johnpye 864 int extpy_import(const struct FilePath *fp, const char *initfunc, const char *partialpath){
197 johnpye 862 char *name;
198     name = ospath_str(fp);
199 johnpye 865 FILE *f;
200 johnpye 872 PyObject *pyfile;
201 johnpye 865
202 johnpye 873 CONSOLE_DEBUG("Importing Python script %s",name);
203 johnpye 865 if(Py_IsInitialized()){
204 johnpye 873 CONSOLE_DEBUG("Python was already initialised");
205 johnpye 865 }else{
206     CONSOLE_DEBUG("INITIALISING PYTHON");
207     Py_Initialize();
208 johnpye 867 CONSOLE_DEBUG("COMPLETED ATTEMPT TO INITIALISE PYTHON");
209 johnpye 865 }
210    
211 johnpye 867 if(!Py_IsInitialized()){
212 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to initialise Python");
213 johnpye 867 CONSOLE_DEBUG("UNABLE TO INITIALIZE PYTHON");
214 johnpye 873 ASC_FREE(name);
215 johnpye 867 return 1;
216     }
217    
218 johnpye 869 initextpy();
219    
220 johnpye 872 pyfile = PyFile_FromString(name,"r");
221     if(pyfile==NULL){
222 johnpye 871 CONSOLE_DEBUG("Failed opening script");
223 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to open '%s' (%s)",partialpath,name);
224     ASC_FREE(name);
225 johnpye 871 return 1;
226     }
227 johnpye 872
228     f = PyFile_AsFile(pyfile);
229     if(f==NULL){
230 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to cast PyObject to FILE*");
231     ASC_FREE(name);
232 johnpye 872 return 1;
233     }
234 johnpye 873
235 johnpye 872 PyRun_AnyFileEx(f,name,1);
236 johnpye 873 /*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 johnpye 871
243 johnpye 873 ERROR_REPORTER_HERE(ASC_PROG_NOTE,"Imported python script '%s' (check console for errors)",partialpath);
244    
245 johnpye 862 ASC_FREE(name);
246 johnpye 873 return 0;
247 johnpye 862 }
248    

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