Addons updated to new doc format
[io.git] / addons / Python / source / IoPython.c
blobe15df5241093904904babe4de0a2c06047afe492
1 //metadoc Python copyrigth Aslak Gronflaten, 2006
2 //metadoc Python license BSD revised
3 /*metadoc Python description
4 This object provides access the world of python.
5 */
6 //metadoc Python credit Based on code by Steve Dekorte
7 //metadoc Python category Server
9 #include "IoPython.h"
10 #include "IoState.h"
11 #include "IoNumber.h"
12 #include "IoList.h"
13 #include "IoDirectory.h"
14 #include <stdlib.h>
15 #include <stdio.h>
17 #define DATA(self) ((PythonData *)IoObject_dataPointer(self))
19 IoTag *IoPython_newTag(void *state)
21 IoTag *tag = IoTag_newWithName_("Python");
22 IoTag_state_(tag, state);
23 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoPython_rawClone);
24 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoPython_free);
25 return tag;
28 IoPython *IoPython_proto(void *state)
30 Py_Initialize();
31 IoObject *self = IoObject_new(state);
32 IoObject_tag_(self, IoPython_newTag(state));
33 IoObject_setDataPointer_(self, PythonData_new());
34 fflush(stdout);
35 IoState_registerProtoWithFunc_(state, self, IoPython_proto);
38 IoMethodTable methodTable[] = {
39 {"credits", IoPython_credits},
40 {"forward", IoPython_forward},
41 {"import", IoPython_import},
42 {"invoke", IoPython_call},
43 {"print", IoPython_print},
44 {NULL, NULL},
46 IoObject_addMethodTable_(self, methodTable);
48 DATA(self)->data = (void *) 1; // Hack
49 return self;
52 IoPython *IoPython_rawClone(IoPython *proto)
54 IoPython *self = IoObject_rawClonePrimitive(proto);
55 IoObject_setDataPointer_(self, PythonData_new());
56 return self;
59 /* ----------------------------------------------------------- */
61 IoPython *IoPython_new(void *state)
63 IoObject *proto = IoState_protoWithInitFunction_(state, IoPython_proto);
64 return IOCLONE(proto);
67 void IoPython_free(IoPython *self)
69 PythonData_free(DATA(self));
71 /* ----------------------------------------------------------- */
73 IoObject *wrap(IoPython *self, PyObject *o) {
74 IoPython *ret = IoPython_new(IOSTATE);
75 DATA(ret)->data = o;
76 return ret;
79 IoObject *IoPython_credits(IoPython *self, IoObject *locals, IoMessage *m)
81 return IOSYMBOL("Python/Io bridge by Aslak Gronflaten");
84 IoObject *IoPython_print(IoPython *self, IoObject *locals, IoMessage *m)
86 PyObject *obj = DATA(self)->data;
87 if(obj > 1) {
88 PyObject_Print(obj, stdout, 0);
90 return self;
93 /**
94 * Convert an Io object to PyObject.
95 * At the moment, we can't pass in any objects, just those that can be translated,
96 * until I build a python wrapper around an io object, reverse of what I did here.
97 * TODO: Memory management!!!
99 PyObject *convertIo(IoObject *self, IoObject *obj) {
100 PyObject *ret;
101 if(ISNUMBER(obj)) {
102 ret = PyFloat_FromDouble(CNUMBER(obj));
103 Py_INCREF(ret);
104 return ret;
106 if(ISSEQ(obj)) {
107 ret = PyString_FromString(CSTRING(obj));
108 Py_INCREF(ret);
109 return ret;
111 printf("Unable to convert parameter to python.\n");
112 return NULL;
116 * Tries to convert the obj to an Io object, if possible. If not, return null.
117 * Can't decref if this method is used on both pFunc and pValue
119 IoObject *convertPy(IoObject *self, PyObject *obj) {
120 //PyObject_Print(obj, stdout, 0);
121 //PyObject *pType = PyObject_Type(obj);
122 //PyObject_Print(pType, stdout, 0);
123 IoObject *ret; // Return value
125 if(PyString_Check(obj)) {
126 // Convert to Io sequence and return.
127 IoSeq *ret = IoSeq_newWithCString_(IOSTATE, PyString_AsString(obj));
128 // TODO:::: Memory management! Who's responsible here! (I am, that's who)
129 return ret;
132 if(PyFloat_Check(obj)) {
133 ret = IoNumber_newWithDouble_(IOSTATE, PyFloat_AS_DOUBLE(obj));
134 //Py_DECREF(obj);
135 return ret;
137 if(PyInt_Check(obj)) {
138 ret = IoNumber_newWithDouble_(IOSTATE, PyInt_AS_LONG(obj));
139 // Decref?
140 return ret;
142 if(PyList_Check(obj)) {
143 // We have a list. So, make an Io list, and convert every element, and insert them.
144 int len = PyList_GET_SIZE(obj);
145 ret = IoList_new(IOSTATE);
146 int i;
147 for(i=0;i<len;i++) {
148 PyObject *o = PyList_GET_ITEM(obj, i);
149 IoObject *x = convertPy(self, o);
150 // insert in list
151 IoList_rawAppend_(ret, x);
153 return ret;
155 if(PyDict_Check(obj)) {
156 // We have a dictionary. Make an Io map, and convert all values.
157 // or should we.... Io's map can only have string keys... hardly a replacement, now is it.
158 // Would be better to build a good wrapper around the python dict.
160 if(PyCallable_Check(obj)) {
161 //ret = IoState_doString_(IOSTATE, "method(return self invoke(\"\")");
162 // TODO: We should return a callable object here... Don't know how though. Yet.
164 return wrap(self, obj);
169 IoObject *IoPython_call_int(IoPython *self, IoObject *locals, IoMessage *m, int argOffset, char *functionName)
171 int argc = IoMessage_argCount(m);
173 PyObject *pModule = DATA(self)->data;
174 if(!pModule) {
175 fprintf(stderr, "We have null pModule for function %s ", functionName);
176 return IONIL(self);
178 if(!PyObject_HasAttrString(pModule, functionName)){
179 fprintf(stderr, "Module has no function %s ", functionName);
180 return IONIL(self);
183 PyObject *pFunc = PyObject_GetAttrString(pModule, functionName);
184 /* pFunc is a new reference */
186 if (pFunc && PyCallable_Check(pFunc)) {
187 PyObject *pArgs = PyTuple_New(argc - argOffset); // argc
188 int i;
189 for(i = argOffset;i<argc;i++) {
190 IoObject *param = IoMessage_locals_valueArgAt_(m, locals, i);
191 PyObject *pyValue = convertIo(self, param);
192 PyTuple_SetItem(pArgs, i-argOffset, pyValue);
194 PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
195 Py_DECREF(pArgs);
196 Py_XDECREF(pFunc);
197 if (pValue != NULL) {
198 return convertPy(self, pValue);
199 } else {
200 if (PyErr_Occurred())
201 PyErr_Print();
202 fprintf(stderr,"Call failed\n");
204 } else {
205 if (PyErr_Occurred())
206 PyErr_Print();
207 else {
208 return convertPy(self, pFunc);
210 fprintf(stderr, "Cannot find python function \"%s\"\n", functionName);
212 return IONIL(self);
215 IoObject *IoPython_forward(IoPython *self, IoObject *locals, IoMessage *m)
217 IoSymbol *name = IoMessage_name(m);
218 char *functionName = IoSeq_asCString(name);
219 return IoPython_call_int(self, locals, m, 0, functionName);
222 IoObject *IoPython_call(IoPython *self, IoObject *locals, IoMessage *m)
224 IoSeq *name = IoMessage_locals_seqArgAt_(m, locals, 0);
225 char *functionName = IoSeq_asCString(name);
226 return IoPython_call_int(self, locals, m, 1, functionName);
231 * Import a module, return reference to it as a Python object
233 IoObject *IoPython_import(IoPython *self, IoObject *locals, IoMessage *m)
235 IoSeq *name = IoMessage_locals_seqArgAt_(m, locals, 0);
236 char *nameString = IoSeq_asCString(name);
238 PyObject *pName, *pModule;
239 pName = PyString_FromString(nameString);
240 /* Error checking of pName left out */
242 pModule = PyImport_Import(pName);
244 if(!pModule) {
245 fprintf(stderr, "Could not find module %s\n", nameString);
246 return IONIL(self);
249 // Set slots (for easier introspection and use from io)
251 PyObject *dict = PyModule_GetDict(pModule);
252 PyObject *keys = PyDict_Keys(dict);
253 int i;
254 for(i = 0;i<PyList_Size(keys);i++) {
255 PyObject *key = PyList_GetItem(keys, i);
256 PyObject *value = PyDict_GetItem(dict, key);
257 // TODO: Not allowed method vall IoSeq_newSymbolWithCString_
258 if(!PyCallable_Check(value)) {// don't want methods blocking the forward
259 IoObject_setSlot_to_(self, IOSYMBOL(PyString_AsString(key)), convertPy(self, value));
265 Py_DECREF(pName);
267 // Now, we've got the module. Wrap it and return it.
268 return wrap(self, pModule);