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 PyObject* py_name; 145 NSString* name; 146 147 if (!PyTuple_Check(item)) { 148 PyErr_Format(PyExc_TypeError, 149 "item %" PY_FORMAT_SIZE_T 150 "d has type %s not tuple", 151 i, Py_TYPE(item)->tp_name); 152 Py_DECREF(seq); 153 return NULL; 154 } 155 156 if (!PyArg_ParseTuple(item, 157 "O!"Py_ARG_BYTES":variableInfo", 158#if PY_MAJOR_VERSION == 2 159 &PyBaseString_Type, 160#else 161 &PyUnicode_Type, 162#endif 163 &py_name, &signature)) { 164 Py_DECREF(seq); 165 return NULL; 166 } 167 168 name = PyObjC_PythonToId(py_name); 169 if (name == NULL && PyErr_Occurred()) { 170 return NULL; 171 } 172 173 value = CFBundleGetDataPointerForName(cfBundle, 174 (CFStringRef)name); 175 if (value == NULL) { 176 if (!skip_undefined) { 177 PyErr_SetString(PyObjCExc_Error, 178 "cannot find a variable"); 179 Py_DECREF(seq); 180 return NULL; 181 } 182 183 } else { 184 PyObject* pyVal = pythonify_c_value(signature, value); 185 if (pyVal == NULL) { 186 Py_DECREF(seq); 187 return NULL; 188 } 189 190 if (PyDict_SetItemString(module_globals, 191 [name UTF8String], pyVal) == -1) { 192 Py_DECREF(seq); 193 Py_DECREF(pyVal); 194 return NULL; 195 } 196 Py_DECREF(pyVal); 197 } 198 } 199 Py_DECREF(seq); 200 Py_INCREF(Py_None); 201 return Py_None; 202} 203 204PyObject* PyObjC_loadBundleFunctions(PyObject* self __attribute__((__unused__)), 205 PyObject* args, PyObject* kwds) 206{ 207static char* keywords[] = { "bundle", "module_globals", "functionInfo", "skip_undefined", NULL }; 208 NSBundle* bundle; 209 PyObject* module_globals; 210 PyObject* functionInfo; 211 int skip_undefined = 1; 212 CFBundleRef cfBundle; 213 PyObject* seq; 214 Py_ssize_t i, len; 215 216 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&OO|i", 217 keywords, PyObjCObject_Convert, &bundle, 218 &module_globals, &functionInfo, &skip_undefined)) { 219 return NULL; 220 } 221 222 223 if (bundle == NULL) { 224 cfBundle = NULL; 225 } else { 226 PyObjC_DURING 227 cfBundle = NSBundle2CFBundle(bundle); 228 229 PyObjC_HANDLER 230 PyObjCErr_FromObjC(localException); 231 cfBundle = NULL; 232 233 PyObjC_ENDHANDLER 234 235 if (cfBundle == NULL && PyErr_Occurred()) { 236 return NULL; 237 } 238 239 if (cfBundle == NULL) { 240 PyErr_Format(PyObjCExc_Error, 241 "Cannot convert NSBundle to CFBundle"); 242 return NULL; 243 } 244 } 245 246 seq = PySequence_Fast(functionInfo, "functionInfo not a sequence"); 247 if (seq == NULL) { 248 return NULL; 249 } 250 251 len = PySequence_Fast_GET_SIZE(seq); 252 for (i = 0; i < len; i++) { 253 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 254 void* value; 255 char* signature; 256 NSString* name; 257 char* c_name; 258 PyObject* doc; 259 PyObject* meta = NULL; 260 261 if (!PyTuple_Check(item)) { 262 PyErr_Format(PyExc_TypeError, 263 "item %" PY_FORMAT_SIZE_T 264 "d has type %s not tuple", 265 i, Py_TYPE(item)->tp_name); 266 Py_DECREF(seq); 267 return NULL; 268 } 269 270 doc = NULL; 271 if (cfBundle != NULL) { 272 if (!PyArg_ParseTuple(item, 273#if PY_MAJOR_VERSION == 2 274 "O&s|SO;functionInfo", 275#else 276 "O&y|UO;functionInfo", 277#endif 278 PyObjCObject_Convert, &name, &signature, &doc, &meta)){ 279 Py_DECREF(seq); 280 return NULL; 281 } 282 if (![name isKindOfClass:[NSString class]]) { 283 PyErr_SetString(PyExc_TypeError, 284 "functionInfo name not a string"); 285 Py_DECREF(seq); 286 return NULL; 287 } 288 289 value = CFBundleGetFunctionPointerForName(cfBundle, 290 (CFStringRef)name); 291 } else { 292 if (!PyArg_ParseTuple(item, 293#if PY_MAJOR_VERSION == 2 294 "ss|SO;functionInfo", 295#else 296 "sy|UO;functionInfo", 297#endif 298 &c_name, &signature, &doc, &meta)){ 299 Py_DECREF(seq); 300 return NULL; 301 } 302 303 value = dlsym(RTLD_DEFAULT, c_name); 304 } 305 if (value == NULL) { 306 if (!skip_undefined) { 307 PyErr_SetString(PyObjCExc_Error, 308 "cannot find a function"); 309 Py_DECREF(seq); 310 return NULL; 311 } 312 } else { 313 PyObject* py_name; 314 if (cfBundle == NULL) { 315 py_name = PyText_FromString(c_name); 316 } else { 317 py_name = PyObjC_IdToPython(name); 318 } 319 PyObject* pyVal = PyObjCFunc_New( 320 py_name, 321 value, 322 signature, 323 doc, 324 meta); 325 if (pyVal == NULL) { 326 Py_DECREF(seq); 327 Py_DECREF(py_name); 328 return NULL; 329 } 330 331 if (PyDict_SetItem(module_globals, 332 py_name, pyVal) == -1) { 333 Py_DECREF(seq); 334 Py_DECREF(py_name); 335 Py_DECREF(pyVal); 336 return NULL; 337 } 338 Py_DECREF(py_name); 339 Py_DECREF(pyVal); 340 } 341 } 342 Py_DECREF(seq); 343 Py_INCREF(Py_None); 344 return Py_None; 345} 346 347typedef void(*function)(void); 348struct functionlist { 349 char* name; 350 function func; 351}; 352 353static function find_function(struct functionlist* functions, PyObject* name) 354{ 355 while (functions->name != NULL) { 356 if (PyObjC_is_ascii_string(name, functions->name)) { 357 return functions->func; 358 } 359 functions++; 360 } 361 return NULL; 362} 363 364PyObject* PyObjC_loadFunctionList(PyObject* self __attribute__((__unused__)), 365 PyObject* args, PyObject* kwds) 366{ 367static char* keywords[] = { "function_list", "module_globals", "functionInfo", "skip_undefined", NULL }; 368 PyObject* pyFunctionsList; 369 PyObject* module_globals; 370 PyObject* functionInfo; 371 int skip_undefined = 1; 372 PyObject* seq; 373 Py_ssize_t i, len; 374 struct functionlist* function_list; 375 376 377 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|i", 378 keywords, &pyFunctionsList, 379 &module_globals, &functionInfo, &skip_undefined)) { 380 return NULL; 381 } 382 383 if (!PyCapsule_CheckExact(pyFunctionsList)) { 384 PyErr_SetString(PyExc_TypeError, "function_list not a PyCapsule"); 385 return NULL; 386 } 387 function_list = PyCapsule_GetPointer(pyFunctionsList, "objc.__inline__"); 388 if (function_list == NULL) { 389 PyErr_SetString(PyExc_ValueError, "no function list"); 390 return NULL; 391 } 392 393 seq = PySequence_Fast(functionInfo, "functionInfo not a sequence"); 394 if (seq == NULL) { 395 return NULL; 396 } 397 398 len = PySequence_Fast_GET_SIZE(seq); 399 for (i = 0; i < len; i++) { 400 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 401 void* value; 402 char* signature; 403 PyObject* name; 404 PyObject* doc; 405 PyObject* meta = NULL; 406 407 if (!PyTuple_Check(item)) { 408 PyErr_Format(PyExc_TypeError, 409 "item %" PY_FORMAT_SIZE_T 410 "d has type %s not tuple", 411 i, Py_TYPE(item)->tp_name); 412 Py_DECREF(seq); 413 return NULL; 414 } 415 416 doc = NULL; 417 if (!PyArg_ParseTuple(item, 418#if PY_MAJOR_VERSION == 2 419 "O!s|O!O:functionInfo tuple", &PyBaseString_Type, 420 421#else 422 "Uy|O!O:functionInfo tuple", 423#endif 424 &name, &signature, 425#if PY_MAJOR_VERSION == 2 426 &PyBaseString_Type, 427#else 428 &PyUnicode_Type, 429#endif 430 431 &doc, &meta)){ 432 Py_DECREF(seq); 433 return NULL; 434 } 435 436 437 value = find_function(function_list, name); 438 if (value == NULL) { 439 if (!skip_undefined) { 440 PyErr_Format(PyObjCExc_Error, 441 "cannot find function %s", name); 442 Py_DECREF(seq); 443 return NULL; 444 } 445 } else { 446 PyObject* pyVal = PyObjCFunc_New( 447 name, 448 value, 449 signature, 450 doc, 451 meta); 452 if (pyVal == NULL) { 453 Py_DECREF(seq); 454 return NULL; 455 } 456 457 if (PyDict_SetItem(module_globals, 458 name, pyVal) == -1) { 459 Py_DECREF(seq); 460 Py_DECREF(pyVal); 461 return NULL; 462 } 463 Py_DECREF(pyVal); 464 } 465 } 466 Py_DECREF(seq); 467 Py_INCREF(Py_None); 468 return Py_None; 469} 470