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 PyObjC_DURING 224 cfBundle = NSBundle2CFBundle(bundle); 225 226 PyObjC_HANDLER 227 PyObjCErr_FromObjC(localException); 228 cfBundle = NULL; 229 230 PyObjC_ENDHANDLER 231 232 if (cfBundle == NULL && PyErr_Occurred()) { 233 return NULL; 234 } 235 236 if (cfBundle == NULL) { 237 PyErr_Format(PyObjCExc_Error, 238 "Cannot convert NSBundle to CFBundle"); 239 return NULL; 240 } 241 242 seq = PySequence_Fast(functionInfo, "functionInfo not a sequence"); 243 if (seq == NULL) { 244 return NULL; 245 } 246 247 len = PySequence_Fast_GET_SIZE(seq); 248 for (i = 0; i < len; i++) { 249 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 250 void* value; 251 char* signature; 252 NSString* name; 253 PyObject* doc; 254 PyObject* meta = NULL; 255 256 if (!PyTuple_Check(item)) { 257 PyErr_Format(PyExc_TypeError, 258 "item %" PY_FORMAT_SIZE_T 259 "d has type %s not tuple", 260 i, Py_TYPE(item)->tp_name); 261 Py_DECREF(seq); 262 return NULL; 263 } 264 265 doc = NULL; 266 if (!PyArg_ParseTuple(item, 267#if PY_MAJOR_VERSION == 2 268 "O&s|SO;functionInfo", 269#else 270 "O&y|UO;functionInfo", 271#endif 272 PyObjCObject_Convert, &name, &signature, &doc, &meta)){ 273 Py_DECREF(seq); 274 return NULL; 275 } 276 277 if (![name isKindOfClass:[NSString class]]) { 278 PyErr_SetString(PyExc_TypeError, 279 "functionInfo name not a string"); 280 Py_DECREF(seq); 281 return NULL; 282 } 283 284 value = CFBundleGetFunctionPointerForName(cfBundle, 285 (CFStringRef)name); 286 if (value == NULL) { 287 if (!skip_undefined) { 288 PyErr_SetString(PyObjCExc_Error, 289 "cannot find a function"); 290 Py_DECREF(seq); 291 return NULL; 292 } 293 } else { 294 PyObject* py_name = PyObjC_IdToPython(name); 295 PyObject* pyVal = PyObjCFunc_New( 296 py_name, 297 value, 298 signature, 299 doc, 300 meta); 301 if (pyVal == NULL) { 302 Py_DECREF(seq); 303 Py_DECREF(py_name); 304 return NULL; 305 } 306 307 if (PyDict_SetItem(module_globals, 308 py_name, pyVal) == -1) { 309 Py_DECREF(seq); 310 Py_DECREF(py_name); 311 Py_DECREF(pyVal); 312 return NULL; 313 } 314 Py_DECREF(py_name); 315 Py_DECREF(pyVal); 316 } 317 } 318 Py_DECREF(seq); 319 Py_INCREF(Py_None); 320 return Py_None; 321} 322 323typedef void(*function)(void); 324struct functionlist { 325 char* name; 326 function func; 327}; 328 329static function find_function(struct functionlist* functions, PyObject* name) 330{ 331 while (functions->name != NULL) { 332 if (PyObjC_is_ascii_string(name, functions->name)) { 333 return functions->func; 334 } 335 functions++; 336 } 337 return NULL; 338} 339 340PyObject* PyObjC_loadFunctionList(PyObject* self __attribute__((__unused__)), 341 PyObject* args, PyObject* kwds) 342{ 343static char* keywords[] = { "function_list", "module_globals", "functionInfo", "skip_undefined", NULL }; 344 PyObject* pyFunctionsList; 345 PyObject* module_globals; 346 PyObject* functionInfo; 347 int skip_undefined = 1; 348 PyObject* seq; 349 Py_ssize_t i, len; 350 struct functionlist* function_list; 351 352 353 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OOO|i", 354 keywords, &pyFunctionsList, 355 &module_globals, &functionInfo, &skip_undefined)) { 356 return NULL; 357 } 358 359 if (!PyCapsule_CheckExact(pyFunctionsList)) { 360 PyErr_SetString(PyExc_TypeError, "function_list not a PyCapsule"); 361 return NULL; 362 } 363 function_list = PyCapsule_GetPointer(pyFunctionsList, "objc.__functionlist__"); 364 if (function_list == NULL) { 365 PyErr_SetString(PyExc_ValueError, "no function list\n"); 366 return NULL; 367 } 368 369 seq = PySequence_Fast(functionInfo, "functionInfo not a sequence"); 370 if (seq == NULL) { 371 return NULL; 372 } 373 374 len = PySequence_Fast_GET_SIZE(seq); 375 for (i = 0; i < len; i++) { 376 PyObject* item = PySequence_Fast_GET_ITEM(seq, i); 377 void* value; 378 char* signature; 379 PyObject* name; 380 PyObject* doc; 381 PyObject* meta = NULL; 382 383 if (!PyTuple_Check(item)) { 384 PyErr_Format(PyExc_TypeError, 385 "item %" PY_FORMAT_SIZE_T 386 "d has type %s not tuple", 387 i, Py_TYPE(item)->tp_name); 388 Py_DECREF(seq); 389 return NULL; 390 } 391 392 doc = NULL; 393 if (!PyArg_ParseTuple(item, 394#if PY_MAJOR_VERSION == 2 395 "O!s|SO:functionInfo tuple", &PyBaseString_Type, 396 397#else 398 "Uy|UO:functionInfo tuple", 399#endif 400 &name, &signature, &doc, &meta)){ 401 Py_DECREF(seq); 402 return NULL; 403 } 404 405 value = find_function(function_list, name); 406 if (value == NULL) { 407 if (!skip_undefined) { 408 PyErr_Format(PyObjCExc_Error, 409 "cannot find function %s", name); 410 Py_DECREF(seq); 411 return NULL; 412 } 413 } else { 414 PyObject* pyVal = PyObjCFunc_New( 415 name, 416 value, 417 signature, 418 doc, 419 meta); 420 if (pyVal == NULL) { 421 Py_DECREF(seq); 422 return NULL; 423 } 424 425 if (PyDict_SetItem(module_globals, 426 name, pyVal) == -1) { 427 Py_DECREF(seq); 428 Py_DECREF(pyVal); 429 return NULL; 430 } 431 Py_DECREF(pyVal); 432 } 433 } 434 Py_DECREF(seq); 435 Py_INCREF(Py_None); 436 return Py_None; 437} 438