home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Languages / python / PyObjC-0.47-MIHS / pyobjc-0.47-src / Modules / ObjC.m < prev    next >
Encoding:
Text File  |  1996-11-14  |  8.4 KB  |  304 lines

  1. /* Copyright (c) 1996 by Lele Gaifax.  All Rights Reserved
  2.  *
  3.  * This software may be used and distributed freely for any purpose
  4.  * provided that this notice is included unchanged on any and all
  5.  * copies. The author does not warrant or guarantee this software in
  6.  * any way.
  7.  *
  8.  * This file is part of the PyObjC package.
  9.  *
  10.  * $RCSfile: ObjC.m,v $
  11.  * $Revision: 1.9 $
  12.  * $Date: 1996/11/15 02:33:42 $
  13.  *
  14.  * Created Tue Jun 18 12:28:42 1996.
  15.  */
  16.  
  17. /* Long time ago, Jon M. Kutemeier wrote a module to interface Python
  18.    with Objective-C and for a while Guido van Rossum "revamped and
  19.    maintained" it. Sadly, on Mon, 22 Jul 1996 Guido announced the he
  20.    will drop that module from the Python distribution. Since I'm a
  21.    NeXTSTEP fan(atic), I considered that a bad news: for months I dreamed
  22.    about working on its beautiful UI from Python; more than that, the
  23.    two languages are so similar that Objective-C may be viewed as the
  24.    compiled cousin of Guido's creation, at least while we all wait for
  25.    a Python compiler...
  26.  
  27.    So I rewrote it: it provides an easier way of sending messages to
  28.    Objective-C objects, and (will) support(s) the GNU Objective-C runtime.
  29.  
  30.    Now I just hope Guido will reconsider his decision... */
  31.  
  32. #include "ObjC.h"
  33. #include "objc_support.h"
  34.  
  35. #ifndef STRINGIFY        // GNUstep defines it.
  36. #define STRINGIFY(a) _STRINGIFY(a)
  37. #define _STRINGIFY(a) #a
  38. #endif
  39.  
  40. static char ObjC_doc[] = "\
  41. Objective-C Interface module Version " STRINGIFY(PyObjC_VERSION) ".\n\
  42. Copyright (C) 1996 - Lele Gaifax <lele@nautilus.eclipse.it>\n\n\
  43. This module implements an Objective-C interface layer, allowing the use\n\
  44. of Objective-C functionalities from Python scripts.\n\n\
  45. You can access an Objective-C class with the `.lookup_class' method,\n\
  46. that returns a Python wrapper around it. Then you can send Objective-C\n\
  47. message to it, for example to get an instance of the class:\n\
  48. \tSyntax A:\t\t\t\tSyntax B:\n\
  49. \tList = ObjC.lookup_class ('List')\tList = ObjC.runtime.List\n\
  50. \talist = List.alloc().init()\t\talist = List()\n\
  51. \tObject = ObjC.lookup_class ('Object')\tObject = ObjC.runtime.Object\n\
  52. \tobj1 = Object.alloc().init()\t\tobj1 = Object()\n\
  53. \talist.addObject__ (obj1)\t\t...\n\
  54. \talist.addObject__ ('Ciao')\n\
  55. \talist.count()\n\
  56. \t>>> 2\n\
  57. \talist[1]\n\
  58. \t>>> 'Ciao'\n\n\
  59. Since Python has a different calling syntax, Objective-C method names\n\
  60. change slightly: given the expression\n\
  61. \tmyself = [[User alloc] initId:1 group:1 andName:\"Lele Gaifax\"];\n\n\
  62. to obtain the same in Python you should use\n\
  63. \tUser = ObjC.runtime.User\n\
  64. \tmyself = User.alloc().initId__group__andName__ (1, 1, \"Lele Gaifax\")\n\n\
  65. or more concisely\n\
  66. \tmyself=ObjC.runtime.User(1,1,\"Lele Gaifax\",init=\"initId:group:andName:\")\n\
  67. \n\
  68. In other words, if the signature of an Objective-C method is\n\
  69. `someMethod:withSecondArg:andAnother:', which takes three arguments, the\n\
  70. Python equivalent results by replacing each colon `:' with a double underscore\n\
  71. `_', then feeding the arguments in row, as usual.\n\
  72. ";
  73.  
  74. char ObjC_load_object_files_doc[] =
  75. FUNDOC("Dynamically load a list of object files",
  76.        ".load_object_files (LIST)",
  77.        "LIST\t: list of filenames to load",
  78.        "None");
  79. PyObject *
  80. ObjC_load_object_files (PyObject *self, PyObject *args)
  81. {
  82. #ifdef GNU_RUNTIME
  83.   
  84. #define errorStream stderr
  85. #define streamBuf "Unable to dynamically load modules"
  86. #define NXPutc(s,c)
  87. #define NXGetMemoryBuffer(a,b,c,d)
  88. #define NXCloseMemory(a,b)
  89.   
  90. #else
  91.   
  92.   NXStream *errorStream;
  93.   char *streamBuf;
  94.   int len, maxLen;
  95.   
  96. #endif
  97.   const char **filenames;
  98.   long ret;
  99.   PyObject *filelist, *file;
  100.   int listsize, i;
  101.  
  102.   if (!PyArg_ParseTuple (args, "O!;list of filenames", &PyList_Type, &filelist))
  103.     return NULL;
  104.  
  105.   listsize = PyList_Size (filelist);
  106.   filenames = alloca ((listsize+1) * sizeof (*filenames));
  107.  
  108. #ifndef GNU_RUNTIME
  109.   errorStream = NXOpenMemory (NULL, 0, NX_WRITEONLY);
  110. #endif
  111.   
  112.   for (i = 0; i < listsize; i++)
  113.     {
  114.       file = PyList_GetItem (filelist, i);
  115.  
  116.       if (!PyString_Check (file))
  117.     {
  118.       PyErr_SetString (ObjC_Error,
  119.                "all list items must be strings");
  120.       return NULL;
  121.     }
  122.       
  123.       filenames[i] = PyString_AsString (file);
  124.     }
  125.  
  126.   filenames[listsize] = NULL;
  127.  
  128.   ret = objc_loadModules (filenames, errorStream, NULL, NULL, NULL);
  129.  
  130.   /* extract the error messages for the exception */
  131.   if (ret)
  132.     {
  133.       NXPutc (errorStream, '\0');
  134.  
  135.       NXGetMemoryBuffer (errorStream, &streamBuf, &len, &maxLen);
  136.       PyErr_SetString (ObjC_Error, streamBuf);
  137.     }
  138.  
  139.   NXCloseMemory (errorStream, NX_FREEBUFFER);
  140.  
  141.   if (ret)
  142.     return NULL;
  143.   else
  144.     {
  145.       Py_INCREF (Py_None);
  146.       return Py_None;
  147.     }
  148. }
  149.  
  150. static char ObjC_lookup_class_doc[] =
  151. FUNDOC("Locate a class in the Objective-C runtime",
  152.        ".lookup_class (CLASS)",
  153.        "CLASS\t: the name of an Objective-C class",
  154.        "An ObjCObject wrapping the given class");
  155. static PyObject *
  156. ObjC_lookup_class (PyObject *self, PyObject *args)
  157. {
  158.   char *classname;
  159.   id    class;
  160.  
  161.   if (!PyArg_ParseTuple (args, "s;class name", &classname))
  162.     return NULL;
  163.  
  164.   if (!(class = LOOKUPCLASS(classname)))
  165.     {
  166. #define ERRMSG "Objective-C class `%s' is unknown to the runtime"
  167.       char errmsg[sizeof ERRMSG + strlen (classname)];
  168.  
  169.       sprintf (errmsg, ERRMSG, classname);
  170.       PyErr_SetString (ObjC_Error, errmsg);
  171. #undef ERRMSG
  172.       return NULL;
  173.     }
  174.  
  175.   return (PyObject *) ObjCObject_new (class);
  176. }
  177.  
  178. char ObjC_list_classes_doc[] =
  179. FUNDOC("Get a list of all known classes names",
  180.        ".list_classes()",
  181.        "none",
  182.        "A list of class names");
  183. PyObject *
  184. ObjC_list_classes (PyObject *self, PyObject *args)
  185. {
  186.   Class classid;
  187.   PyObject *list;
  188. #ifdef GNU_RUNTIME
  189.  
  190.   void *es = NULL;
  191. #define ENUMERATE_CLASSES(c) (c = objc_next_class (&es))
  192.  
  193. #else
  194.  
  195.   NXHashTable *class_hash = objc_getClasses();
  196.   NXHashState state = NXInitHashState (class_hash);
  197. #define ENUMERATE_CLASSES(c) (NXNextHashState (class_hash, &state, (void**) &c))
  198.  
  199. #endif
  200.   
  201.   if (!PyArg_ParseTuple (args, ""))
  202.     return NULL;
  203.  
  204.   list = PyList_New (0);
  205.   if (list == NULL)
  206.     return NULL;
  207.   
  208.   while (ENUMERATE_CLASSES(classid))
  209.     {
  210.       ObjCObject *item = ObjCObject_new (classid);
  211.       
  212.       if (item == NULL || PyList_Append (list, (PyObject *)item) < 0)
  213.     {
  214.       Py_XDECREF(item);
  215.       Py_DECREF(list);
  216.       return NULL;
  217.     }
  218.       Py_DECREF(item);
  219.     }
  220.  
  221.   return list;
  222. }
  223.  
  224. static char ObjC_make_pointer_doc[] =
  225. FUNDOC("Cast an integer value to a generic pointer.",
  226.        ".make_pointer (INT)",
  227.        "INT\t: the integer value",
  228.        "An ObjCPointer instance");
  229. static PyObject *
  230. ObjC_make_pointer (PyObject *self, PyObject *args)
  231. {
  232.   long value;
  233.  
  234.   if (PyArg_ParseTuple (args, "l;an integer", &value))
  235.     return (PyObject *) ObjCPointer_new ((void *) value, @encode (void));
  236.  
  237.   return NULL;
  238. }
  239.                 
  240. static PyMethodDef ObjC_methods[] =
  241. {
  242.   { "load_object_files",    (PyCFunction) ObjC_load_object_files,    METH_VARARGS,    ObjC_load_object_files_doc },
  243.   { "lookup_class",        (PyCFunction) ObjC_lookup_class,    METH_VARARGS,    ObjC_lookup_class_doc },
  244.   { "list_classes",        (PyCFunction) ObjC_list_classes,    METH_VARARGS,    ObjC_list_classes_doc },
  245.   { "make_pointer",        (PyCFunction) ObjC_make_pointer,    METH_VARARGS,    ObjC_make_pointer_doc },
  246.   { 0, 0, 0, 0 }
  247. };
  248.  
  249. PyObject *ObjC_Error;
  250.  
  251. #include "OC_PythonBundle.h"
  252. #include "OC_Pasteboard.h"
  253.  
  254. void
  255. initObjC()
  256. {
  257.   PyObject *m, *d;
  258.   extern void initObjCStreams (void);
  259.   
  260.   m = Py_InitModule4 ("ObjC", ObjC_methods, ObjC_doc, NULL, PYTHON_API_VERSION);
  261.   d = PyModule_GetDict (m);
  262.  
  263.   ObjC_Error = PyString_FromString ("ObjC.error");
  264.   PyDict_SetItemString (d, "error", ObjC_Error);
  265.  
  266.   PyDict_SetItemString (d, "runtime", (PyObject *) ObjCRuntime_new());
  267.   PyDict_SetItemString (d, "__version__", PyFloat_FromDouble (PyObjC_VERSION));
  268.  
  269.   /**
  270.   *** Force +initialize on these classes before any others due to an
  271.   *** initialization order dependency in the 3.3 [and possibly other]
  272.   *** AppKit
  273.   **/
  274.   [LOOKUPCLASS("Application") class];
  275.  
  276.   // Force the load of these classes/categories
  277.   [OC_PythonBundle class];
  278.   oc_pasteboard_ensure_link();
  279.   
  280.   // Initialize the ObjCStreams module...
  281.   initObjCStreams();
  282.  
  283.   // ...and insert it as ``streams'' in the module's dictionary
  284.   m = PyImport_ImportModule ("ObjCStreams");
  285.   if (m)
  286.     {
  287.       PyDict_SetItemString (d, "streams", m);
  288.       Py_DECREF (m);
  289.     }
  290.   
  291.   if (PyErr_Occurred())
  292.     Py_FatalError ("can't initialize module ObjC");
  293.   
  294. #if defined(WITH_THREAD) && !defined(GNU_RUNTIME)
  295.   objc_setMultithreaded (1);
  296. #endif
  297. }
  298.  
  299. /*
  300. ** Local Variables:
  301. ** change-log-default-name:"../ChangeLog.PyObjC"
  302. ** End:
  303. */
  304.