home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1996 by Lele Gaifax. All Rights Reserved
- *
- * This software may be used and distributed freely for any purpose
- * provided that this notice is included unchanged on any and all
- * copies. The author does not warrant or guarantee this software in
- * any way.
- *
- * This file is part of the PyObjC package.
- *
- * $RCSfile: ObjC.m,v $
- * $Revision: 1.9 $
- * $Date: 1996/11/15 02:33:42 $
- *
- * Created Tue Jun 18 12:28:42 1996.
- */
-
- /* Long time ago, Jon M. Kutemeier wrote a module to interface Python
- with Objective-C and for a while Guido van Rossum "revamped and
- maintained" it. Sadly, on Mon, 22 Jul 1996 Guido announced the he
- will drop that module from the Python distribution. Since I'm a
- NeXTSTEP fan(atic), I considered that a bad news: for months I dreamed
- about working on its beautiful UI from Python; more than that, the
- two languages are so similar that Objective-C may be viewed as the
- compiled cousin of Guido's creation, at least while we all wait for
- a Python compiler...
-
- So I rewrote it: it provides an easier way of sending messages to
- Objective-C objects, and (will) support(s) the GNU Objective-C runtime.
-
- Now I just hope Guido will reconsider his decision... */
-
- #include "ObjC.h"
- #include "objc_support.h"
-
- #ifndef STRINGIFY // GNUstep defines it.
- #define STRINGIFY(a) _STRINGIFY(a)
- #define _STRINGIFY(a) #a
- #endif
-
- static char ObjC_doc[] = "\
- Objective-C Interface module Version " STRINGIFY(PyObjC_VERSION) ".\n\
- Copyright (C) 1996 - Lele Gaifax <lele@nautilus.eclipse.it>\n\n\
- This module implements an Objective-C interface layer, allowing the use\n\
- of Objective-C functionalities from Python scripts.\n\n\
- You can access an Objective-C class with the `.lookup_class' method,\n\
- that returns a Python wrapper around it. Then you can send Objective-C\n\
- message to it, for example to get an instance of the class:\n\
- \tSyntax A:\t\t\t\tSyntax B:\n\
- \tList = ObjC.lookup_class ('List')\tList = ObjC.runtime.List\n\
- \talist = List.alloc().init()\t\talist = List()\n\
- \tObject = ObjC.lookup_class ('Object')\tObject = ObjC.runtime.Object\n\
- \tobj1 = Object.alloc().init()\t\tobj1 = Object()\n\
- \talist.addObject__ (obj1)\t\t...\n\
- \talist.addObject__ ('Ciao')\n\
- \talist.count()\n\
- \t>>> 2\n\
- \talist[1]\n\
- \t>>> 'Ciao'\n\n\
- Since Python has a different calling syntax, Objective-C method names\n\
- change slightly: given the expression\n\
- \tmyself = [[User alloc] initId:1 group:1 andName:\"Lele Gaifax\"];\n\n\
- to obtain the same in Python you should use\n\
- \tUser = ObjC.runtime.User\n\
- \tmyself = User.alloc().initId__group__andName__ (1, 1, \"Lele Gaifax\")\n\n\
- or more concisely\n\
- \tmyself=ObjC.runtime.User(1,1,\"Lele Gaifax\",init=\"initId:group:andName:\")\n\
- \n\
- In other words, if the signature of an Objective-C method is\n\
- `someMethod:withSecondArg:andAnother:', which takes three arguments, the\n\
- Python equivalent results by replacing each colon `:' with a double underscore\n\
- `_', then feeding the arguments in row, as usual.\n\
- ";
-
- char ObjC_load_object_files_doc[] =
- FUNDOC("Dynamically load a list of object files",
- ".load_object_files (LIST)",
- "LIST\t: list of filenames to load",
- "None");
- PyObject *
- ObjC_load_object_files (PyObject *self, PyObject *args)
- {
- #ifdef GNU_RUNTIME
-
- #define errorStream stderr
- #define streamBuf "Unable to dynamically load modules"
- #define NXPutc(s,c)
- #define NXGetMemoryBuffer(a,b,c,d)
- #define NXCloseMemory(a,b)
-
- #else
-
- NXStream *errorStream;
- char *streamBuf;
- int len, maxLen;
-
- #endif
- const char **filenames;
- long ret;
- PyObject *filelist, *file;
- int listsize, i;
-
- if (!PyArg_ParseTuple (args, "O!;list of filenames", &PyList_Type, &filelist))
- return NULL;
-
- listsize = PyList_Size (filelist);
- filenames = alloca ((listsize+1) * sizeof (*filenames));
-
- #ifndef GNU_RUNTIME
- errorStream = NXOpenMemory (NULL, 0, NX_WRITEONLY);
- #endif
-
- for (i = 0; i < listsize; i++)
- {
- file = PyList_GetItem (filelist, i);
-
- if (!PyString_Check (file))
- {
- PyErr_SetString (ObjC_Error,
- "all list items must be strings");
- return NULL;
- }
-
- filenames[i] = PyString_AsString (file);
- }
-
- filenames[listsize] = NULL;
-
- ret = objc_loadModules (filenames, errorStream, NULL, NULL, NULL);
-
- /* extract the error messages for the exception */
- if (ret)
- {
- NXPutc (errorStream, '\0');
-
- NXGetMemoryBuffer (errorStream, &streamBuf, &len, &maxLen);
- PyErr_SetString (ObjC_Error, streamBuf);
- }
-
- NXCloseMemory (errorStream, NX_FREEBUFFER);
-
- if (ret)
- return NULL;
- else
- {
- Py_INCREF (Py_None);
- return Py_None;
- }
- }
-
- static char ObjC_lookup_class_doc[] =
- FUNDOC("Locate a class in the Objective-C runtime",
- ".lookup_class (CLASS)",
- "CLASS\t: the name of an Objective-C class",
- "An ObjCObject wrapping the given class");
- static PyObject *
- ObjC_lookup_class (PyObject *self, PyObject *args)
- {
- char *classname;
- id class;
-
- if (!PyArg_ParseTuple (args, "s;class name", &classname))
- return NULL;
-
- if (!(class = LOOKUPCLASS(classname)))
- {
- #define ERRMSG "Objective-C class `%s' is unknown to the runtime"
- char errmsg[sizeof ERRMSG + strlen (classname)];
-
- sprintf (errmsg, ERRMSG, classname);
- PyErr_SetString (ObjC_Error, errmsg);
- #undef ERRMSG
- return NULL;
- }
-
- return (PyObject *) ObjCObject_new (class);
- }
-
- char ObjC_list_classes_doc[] =
- FUNDOC("Get a list of all known classes names",
- ".list_classes()",
- "none",
- "A list of class names");
- PyObject *
- ObjC_list_classes (PyObject *self, PyObject *args)
- {
- Class classid;
- PyObject *list;
- #ifdef GNU_RUNTIME
-
- void *es = NULL;
- #define ENUMERATE_CLASSES(c) (c = objc_next_class (&es))
-
- #else
-
- NXHashTable *class_hash = objc_getClasses();
- NXHashState state = NXInitHashState (class_hash);
- #define ENUMERATE_CLASSES(c) (NXNextHashState (class_hash, &state, (void**) &c))
-
- #endif
-
- if (!PyArg_ParseTuple (args, ""))
- return NULL;
-
- list = PyList_New (0);
- if (list == NULL)
- return NULL;
-
- while (ENUMERATE_CLASSES(classid))
- {
- ObjCObject *item = ObjCObject_new (classid);
-
- if (item == NULL || PyList_Append (list, (PyObject *)item) < 0)
- {
- Py_XDECREF(item);
- Py_DECREF(list);
- return NULL;
- }
- Py_DECREF(item);
- }
-
- return list;
- }
-
- static char ObjC_make_pointer_doc[] =
- FUNDOC("Cast an integer value to a generic pointer.",
- ".make_pointer (INT)",
- "INT\t: the integer value",
- "An ObjCPointer instance");
- static PyObject *
- ObjC_make_pointer (PyObject *self, PyObject *args)
- {
- long value;
-
- if (PyArg_ParseTuple (args, "l;an integer", &value))
- return (PyObject *) ObjCPointer_new ((void *) value, @encode (void));
-
- return NULL;
- }
-
- static PyMethodDef ObjC_methods[] =
- {
- { "load_object_files", (PyCFunction) ObjC_load_object_files, METH_VARARGS, ObjC_load_object_files_doc },
- { "lookup_class", (PyCFunction) ObjC_lookup_class, METH_VARARGS, ObjC_lookup_class_doc },
- { "list_classes", (PyCFunction) ObjC_list_classes, METH_VARARGS, ObjC_list_classes_doc },
- { "make_pointer", (PyCFunction) ObjC_make_pointer, METH_VARARGS, ObjC_make_pointer_doc },
- { 0, 0, 0, 0 }
- };
-
- PyObject *ObjC_Error;
-
- #include "OC_PythonBundle.h"
- #include "OC_Pasteboard.h"
-
- void
- initObjC()
- {
- PyObject *m, *d;
- extern void initObjCStreams (void);
-
- m = Py_InitModule4 ("ObjC", ObjC_methods, ObjC_doc, NULL, PYTHON_API_VERSION);
- d = PyModule_GetDict (m);
-
- ObjC_Error = PyString_FromString ("ObjC.error");
- PyDict_SetItemString (d, "error", ObjC_Error);
-
- PyDict_SetItemString (d, "runtime", (PyObject *) ObjCRuntime_new());
- PyDict_SetItemString (d, "__version__", PyFloat_FromDouble (PyObjC_VERSION));
-
- /**
- *** Force +initialize on these classes before any others due to an
- *** initialization order dependency in the 3.3 [and possibly other]
- *** AppKit
- **/
- [LOOKUPCLASS("Application") class];
-
- // Force the load of these classes/categories
- [OC_PythonBundle class];
- oc_pasteboard_ensure_link();
-
- // Initialize the ObjCStreams module...
- initObjCStreams();
-
- // ...and insert it as ``streams'' in the module's dictionary
- m = PyImport_ImportModule ("ObjCStreams");
- if (m)
- {
- PyDict_SetItemString (d, "streams", m);
- Py_DECREF (m);
- }
-
- if (PyErr_Occurred())
- Py_FatalError ("can't initialize module ObjC");
-
- #if defined(WITH_THREAD) && !defined(GNU_RUNTIME)
- objc_setMultithreaded (1);
- #endif
- }
-
- /*
- ** Local Variables:
- ** change-log-default-name:"../ChangeLog.PyObjC"
- ** End:
- */
-