1/* 2 * This module exports a function to load variables in a bundle 3 * 4 * NOTE: The interface is specified with NSBundles, but we have to 5 * use CFBundles in the implementation. This is not portable to GNUstep :-( 6 */ 7#include "pyobjc.h" 8 9#include <CoreFoundation/CoreFoundation.h> 10#import <Foundation/NSBundle.h> 11#import <Foundation/NSURL.h> 12 13#include <dlfcn.h> 14 15static CFBundleRef 16NSBundle2CFBundle(NSBundle* bundle) 17{ 18 CFURLRef bundleURL; 19 20 bundleURL = (CFURLRef)[NSURL fileURLWithPath:[bundle bundlePath]]; 21 return CFBundleCreate( 22 kCFAllocatorDefault, 23 bundleURL); 24} 25 26PyObject* PyObjC_loadSpecialVar( 27 PyObject* self __attribute__((__unused__)), 28 PyObject* args, PyObject* kwds) 29{ 30static char* keywords[] = { "bundle", "module_globals", "typeid", "name", "skip_undefined", NULL }; 31 32 NSBundle* bundle; 33 NSString* name; 34 PyObject* module_globals; 35 Py_ssize_t typeid; 36 Py_ssize_t skip_undefined = 1; 37 CFBundleRef cfBundle; 38 void* value; 39 40 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&OiO&|i", 41 keywords, PyObjCObject_Convert, &bundle, 42 &module_globals, &typeid, 43 PyObjCObject_Convert, &name, &skip_undefined)) { 44 return NULL; 45 } 46 47 48 PyObjC_DURING 49 cfBundle = NSBundle2CFBundle(bundle); 50 51 PyObjC_HANDLER 52 PyObjCErr_FromObjC(localException); 53 cfBundle = NULL; 54 55 PyObjC_ENDHANDLER 56 57 if (cfBundle == NULL) { 58 if (PyErr_Occurred()) { 59 return NULL; 60 } 61 PyErr_Format(PyObjCExc_Error, 62 "Cannot convert NSBundle to CFBundle"); 63 return NULL; 64 } 65 66 if (![name isKindOfClass:[NSString class]]) { 67 PyErr_SetString(PyExc_TypeError, 68 "variable name not a string"); 69 return NULL; 70 } 71 72 value = CFBundleGetDataPointerForName(cfBundle, (CFStringRef)name); 73 if (value == NULL) { 74 if (!skip_undefined) { 75 PyErr_SetString(PyObjCExc_Error, 76 "cannot find a variable"); 77 return NULL; 78 } 79 80 } else { 81 PyObject* pyVal = PyObjCCF_NewSpecial2(typeid, value); 82 if (pyVal == NULL) { 83 return NULL; 84 } 85 86 if (PyDict_SetItemString(module_globals, 87 [name UTF8String], pyVal) == -1) { 88 Py_DECREF(pyVal); 89 return NULL; 90 } 91 Py_DECREF(pyVal); 92 } 93 Py_INCREF(Py_None); 94 return Py_None; 95} 96 97PyObject* PyObjC_loadBundleVariables(PyObject* self __attribute__((__unused__)), 98 PyObject* args, PyObject* kwds) 99{ 100static char* keywords[] = { "bundle", "module_globals", "variableInfo", "skip_undefined", NULL }; 101 NSBundle* bundle; 102 PyObject* module_globals; 103 PyObject* variableInfo; 104 Py_ssize_t skip_undefined = 1; 105 CFBundleRef cfBundle; 106 PyObject* seq; 107 Py_ssize_t i, len; 108 109 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&OO|i", 110 keywords, PyObjCObject_Convert, &bundle, 111 &module_globals, &variableInfo, &skip_undefined)) { 112 return NULL; 113 } 114 115 116 PyObjC_DURING 117 cfBundle = NSBundle2CFBundle(bundle); 118 119 PyObjC_HANDLER 120 PyObjCErr_FromObjC(localException); 121 cfBundle = NULL; 122 123 PyObjC_ENDHANDLER 124 125 if (cfBundle == NULL) { 126 if (PyErr_Occurred()) { 127 return NULL; 128 } 129 PyErr_Format(PyObjCExc_Error, 130 "Cannot convert NSBundle to CFBundle"); 131 return NULL; 132 } 133 134 seq = PySequence_Fast(variableInfo, "variableInfo not a sequence"); 135 if (seq == NULL) { 136 return NULL; 137 } 138 139 len = PySequence_Fast_GET_SIZE(seq); 140 for (i = 0; i < len; i++) { 141 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 142 void* value; 143 char* signature; 144 NSString* name; 145 146 if (!PyTuple_Check(item)) { 147 PyErr_Format(PyExc_TypeError, 148 "item %" PY_FORMAT_SIZE_T 149 "d has type %s not tuple", 150 i, item->ob_type->tp_name); 151 Py_DECREF(seq); 152 return NULL; 153 } 154 155 if (!PyArg_ParseTuple(item, "O&s:variableInfo", 156 PyObjCObject_Convert, &name, &signature)) { 157 Py_DECREF(seq); 158 return NULL; 159 } 160 161 if (![name isKindOfClass:[NSString class]]) { 162 PyErr_SetString(PyExc_TypeError, 163 "variable name not a string"); 164 Py_DECREF(seq); 165 return NULL; 166 } 167 168 value = CFBundleGetDataPointerForName(cfBundle, 169 (CFStringRef)name); 170 if (value == NULL) { 171 if (!skip_undefined) { 172 PyErr_SetString(PyObjCExc_Error, 173 "cannot find a variable"); 174 Py_DECREF(seq); 175 return NULL; 176 } 177 178 } else { 179 PyObject* pyVal = pythonify_c_value(signature, value); 180 if (pyVal == NULL) { 181 Py_DECREF(seq); 182 return NULL; 183 } 184 185 if (PyDict_SetItemString(module_globals, 186 [name UTF8String], pyVal) == -1) { 187 Py_DECREF(seq); 188 Py_DECREF(pyVal); 189 return NULL; 190 } 191 Py_DECREF(pyVal); 192 } 193 } 194 Py_DECREF(seq); 195 Py_INCREF(Py_None); 196 return Py_None; 197} 198 199PyObject* PyObjC_loadBundleFunctions(PyObject* self __attribute__((__unused__)), 200 PyObject* args, PyObject* kwds) 201{ 202static char* keywords[] = { "bundle", "module_globals", "functionInfo", "skip_undefined", NULL }; 203 NSBundle* bundle; 204 PyObject* module_globals; 205 PyObject* functionInfo; 206 int skip_undefined = 1; 207 CFBundleRef cfBundle; 208 PyObject* seq; 209 Py_ssize_t i, len; 210 211 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&OO|i", 212 keywords, PyObjCObject_Convert, &bundle, 213 &module_globals, &functionInfo, &skip_undefined)) { 214 return NULL; 215 } 216 217 218 PyObjC_DURING 219 cfBundle = NSBundle2CFBundle(bundle); 220 221 PyObjC_HANDLER 222 PyObjCErr_FromObjC(localException); 223 cfBundle = NULL; 224 225 PyObjC_ENDHANDLER 226 227 if (cfBundle == NULL && PyErr_Occurred()) { 228 return NULL; 229 } 230 231 if (cfBundle == NULL) { 232 PyErr_Format(PyObjCExc_Error, 233 "Cannot convert NSBundle to CFBundle"); 234 return NULL; 235 } 236 237 seq = PySequence_Fast(functionInfo, "functionInfo not a sequence"); 238 if (seq == NULL) { 239 return NULL; 240 } 241 242 len = PySequence_Fast_GET_SIZE(seq); 243 for (i = 0; i < len; i++) { 244 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 245 void* value; 246 char* signature; 247 NSString* name; 248 PyObject* doc; 249 PyObject* meta = NULL; 250 251 if (!PyTuple_Check(item)) { 252 PyErr_Format(PyExc_TypeError, 253 "item %" PY_FORMAT_SIZE_T 254 "d has type %s not tuple", 255 i, item->ob_type->tp_name); 256 Py_DECREF(seq); 257 return NULL; 258 } 259 260 doc = NULL; 261 if (!PyArg_ParseTuple(item, "O&s|SO;functionInfo", 262 PyObjCObject_Convert, &name, &signature, &doc, &meta)){ 263 Py_DECREF(seq); 264 return NULL; 265 } 266 267 if (![name isKindOfClass:[NSString class]]) { 268 PyErr_SetString(PyExc_TypeError, 269 "functionInfo name not a string"); 270 Py_DECREF(seq); 271 return NULL; 272 } 273 274 value = CFBundleGetFunctionPointerForName(cfBundle, 275 (CFStringRef)name); 276 if (value == NULL) { 277 if (!skip_undefined) { 278 PyErr_SetString(PyObjCExc_Error, 279 "cannot find a function"); 280 Py_DECREF(seq); 281 return NULL; 282 } 283 } else { 284 PyObject* py_name = PyObjC_IdToPython(name); 285 PyObject* pyVal = PyObjCFunc_New( 286 py_name, 287 value, 288 signature, 289 doc, 290 meta); 291 if (pyVal == NULL) { 292 Py_DECREF(seq); 293 Py_DECREF(py_name); 294 return NULL; 295 } 296 297 if (PyDict_SetItem(module_globals, 298 py_name, pyVal) == -1) { 299 Py_DECREF(seq); 300 Py_DECREF(py_name); 301 Py_DECREF(pyVal); 302 return NULL; 303 } 304 Py_DECREF(py_name); 305 Py_DECREF(pyVal); 306 } 307 } 308 Py_DECREF(seq); 309 Py_INCREF(Py_None); 310 return Py_None; 311} 312 313typedef void(*function)(void); 314struct functionlist { 315 char* name; 316 function func; 317}; 318 319static function find_function(struct functionlist* functions, char* name) 320{ 321 while (functions->name != NULL) { 322 if (strcmp(functions->name, name) == 0) { 323 return functions->func; 324 } 325 functions++; 326 } 327 return NULL; 328} 329 330PyObject* PyObjC_loadFunctionList(PyObject* self __attribute__((__unused__)), 331 PyObject* args, PyObject* kwds) 332{ 333static char* keywords[] = { "function_list", "module_globals", "functionInfo", "skip_undefined", NULL }; 334 PyObject* pyFunctionsList; 335 PyObject* module_globals; 336 PyObject* functionInfo; 337 int skip_undefined = 1; 338 PyObject* seq; 339 Py_ssize_t i, len; 340 struct functionlist* function_list; 341 342 343 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|i", 344 keywords, &pyFunctionsList, 345 &module_globals, &functionInfo, &skip_undefined)) { 346 return NULL; 347 } 348 349 if (!PyCObject_Check(pyFunctionsList)) { 350 PyErr_SetString(PyExc_TypeError, "function_list not a CObject"); 351 return NULL; 352 } 353 function_list = PyCObject_AsVoidPtr(pyFunctionsList); 354 if (function_list == NULL) { 355 PyErr_SetString(PyExc_ValueError, "no function list\n"); 356 return NULL; 357 } 358 359 seq = PySequence_Fast(functionInfo, "functionInfo not a sequence"); 360 if (seq == NULL) { 361 return NULL; 362 } 363 364 len = PySequence_Fast_GET_SIZE(seq); 365 for (i = 0; i < len; i++) { 366 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 367 void* value; 368 char* signature; 369 char* name; 370 PyObject* doc; 371 PyObject* meta = NULL; 372 373 if (!PyTuple_Check(item)) { 374 PyErr_Format(PyExc_TypeError, 375 "item %" PY_FORMAT_SIZE_T 376 "d has type %s not tuple", 377 i, item->ob_type->tp_name); 378 Py_DECREF(seq); 379 return NULL; 380 } 381 382 doc = NULL; 383 if (!PyArg_ParseTuple(item, "ss|SO:functionInfo tuple", 384 &name, &signature, &doc, &meta)){ 385 Py_DECREF(seq); 386 return NULL; 387 } 388 389 value = find_function(function_list, name); 390 if (value == NULL) { 391 if (!skip_undefined) { 392 PyErr_Format(PyObjCExc_Error, 393 "cannot find function %s", name); 394 Py_DECREF(seq); 395 return NULL; 396 } 397 } else { 398 PyObject* py_name = PyString_FromString(name); 399 PyObject* pyVal = PyObjCFunc_New( 400 py_name, 401 value, 402 signature, 403 doc, 404 meta); 405 if (pyVal == NULL) { 406 Py_DECREF(seq); 407 Py_DECREF(py_name); 408 return NULL; 409 } 410 411 if (PyDict_SetItem(module_globals, 412 py_name, pyVal) == -1) { 413 Py_DECREF(seq); 414 Py_DECREF(py_name); 415 Py_DECREF(pyVal); 416 return NULL; 417 } 418 Py_DECREF(py_name); 419 Py_DECREF(pyVal); 420 } 421 } 422 Py_DECREF(seq); 423 Py_INCREF(Py_None); 424 return Py_None; 425} 426