1/* 2 * Workaround to make NSAppicationMain more usable from Python. 3 */ 4#include <Python.h> 5#include "pyobjc-api.h" 6 7#import <AppKit/AppKit.h> 8 9static PyObject* 10objc_NSApplicationMain( 11 PyObject* self __attribute__((__unused__)), 12 PyObject* args, 13 PyObject* kwds) 14{ 15static char* keywords[] = { "argv", NULL }; 16 char** argv = NULL; 17 int argc; 18 PyObject* arglist; 19 int i; 20 PyObject* v; 21 int res; 22 23 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:NSApplicationMain", 24 keywords, &arglist)) { 25 return NULL; 26 } 27 28 if (!PySequence_Check(arglist)) { 29 PyErr_SetString(PyExc_TypeError, 30 "NSApplicationMain: need list of strings as argument"); 31 return NULL; 32 } 33 34 argc = PySequence_Size(arglist); 35 argv = calloc((argc + 1), sizeof(char**)); 36 if (argv == NULL) { 37 PyErr_SetString(PyExc_MemoryError, 38 "Out of memory"); 39 return NULL; 40 } 41 42 for (i = 0; i < argc; i++) { 43 v = PySequence_GetItem(arglist, i); 44 if (v == NULL) { 45 goto error_cleanup; 46 } 47 if (!PyString_Check(v)) { 48 PyErr_SetString(PyExc_TypeError, 49 "NSApplicationMain: need list of strings " 50 "as argument"); 51 goto error_cleanup; 52 } 53 54 argv[i] = strdup(PyString_AsString(v)); 55 if (argv[i] == NULL) { 56 PyErr_SetString(PyExc_MemoryError, 57 "Out of memory"); 58 goto error_cleanup; 59 } 60 } 61 62 argv[argc] = NULL; 63 64#if 0 65 /* 66 * NSApplicationMain on MacOS X completely ignores its arguments and 67 * reads the argv from the shared NSProcessInfo. We *HACK* around this 68 * by setting a (private) instance variable of the object. 69 * 70 * This code is evil. Look away if you're easily scared. 71 * 72 * This doesn't work in 64-bit mode however. Therefore this code 73 * is now disabled. This shouldn't make a difference when using 74 * py2app or Xcode's PyObjC templates. 75 */ 76 { 77 typedef struct { 78 @defs(NSProcessInfo) 79 } NSProcessInfoStruct; 80 81 NSMutableArray *newarglist = [[NSMutableArray alloc] init]; 82 NSProcessInfo *processInfo = [NSProcessInfo processInfo]; 83 char **anArg = argv; 84 85 while(*anArg) { 86 [newarglist addObject: 87 [NSString stringWithUTF8String: *anArg]]; 88 anArg++; 89 } 90 91 /* Don't release the orignal arguments, because we don't know 92 * if the list is owned by the processInfo object. 93 * 94 *[((NSProcessInfoStruct *)processInfo)->arguments release]; 95 */ 96 ((NSProcessInfoStruct *)processInfo)->arguments = newarglist; 97 } 98#endif 99 100 PyObjC_DURING 101 res = NSApplicationMain(argc, (const char**)argv); 102 PyObjC_HANDLER 103 PyObjCErr_FromObjC(localException); 104 res = -1; 105 PyObjC_ENDHANDLER 106 107 for (i = 0; i < argc; i++) { 108 free(argv[i]); 109 } 110 free(argv); 111 112 if (res == -1 && PyErr_Occurred()) 113 return NULL; 114 return PyInt_FromLong(res); 115 116error_cleanup: 117 if (argv != NULL) { 118 for (i = 0; i < argc; i++) { 119 if (argv[i] != NULL) { 120 free(argv[i]); 121 argv[i] = NULL; 122 } 123 } 124 free(argv); 125 argv = NULL; 126 } 127 128 return NULL; 129} 130 131 132static PyMethodDef mod_methods[] = { 133 { 134 "NSApplicationMain", 135 (PyCFunction)objc_NSApplicationMain, 136 METH_VARARGS|METH_KEYWORDS, 137 "int NSApplicationMain(int argc, const char *argv[]);" 138 }, 139 { 0, 0, 0, 0 } /* sentinel */ 140}; 141 142void init_appmain(void); 143void init_appmain(void) 144{ 145 PyObject* m = Py_InitModule4("_appmain", mod_methods, "", NULL, 146 PYTHON_API_VERSION); 147 148 PyObjC_ImportAPI(m); 149} 150