Re: [Pyobjc-dev] OC_PythonString implementation
Brought to you by:
ronaldoussoren
From: Ronald O. <ous...@ci...> - 2003-02-07 22:17:25
|
And below is unicode-object.m, a subclass of PyUnicode_Type that stores a reference to an NSString value. This isn't working entirely correctly yet, that's why I haven't checked it in yet. If you call ObjCUnicode_New in the __pyobjc_PythonObject__ method for NSString objects NSString values are proxied using a unicode object, and calling the method 'pyobjc_NSString' will retrieve a 'plain' proxy for the NSString object (making it possible to call NSString methods). This will crash your interpreter, probably due to a memory management bug. Ronald /* * Custom subclass of PyUnicode_Type, to allow for transparent bridging of * strings */ #include <Python.h> #include "pyobjc.h" #include "objc_support.h" typedef struct { PyUnicodeObject base; PyObject* weakrefs; id nsstr; } ObjCUnicodeObject; PyDoc_STRVAR(class_doc, "objc.pyobjc_unicode\n" "\n" "Subclass of unicode for representing NSString values. Use \n" "the method pyobjc_NSString to access the NSString. \n" "Note that instances are immutable and won't be updated when\n" "the value of the NSString changes." ); static void class_dealloc(PyObject* obj) { PyObject* weakrefs = ((ObjCUnicodeObject*)obj)->weakrefs; id nsstr = ((ObjCUnicodeObject*)obj)->nsstr; if (weakrefs) { PyObject_ClearWeakRefs(obj); } [nsstr release]; PyMem_Free(((PyUnicodeObject*)obj)->str); PyObject_Del(obj); } static PyObject* ObjCUnicode_pyobjc_NSString(PyObject* self) { return ObjCObject_New( *(id*)(((char*)self) +sizeof(PyUnicodeObject) + sizeof(PyObject*))); } static PyMethodDef class_methods[] = { { "pyobjc_NSString", (PyCFunction)ObjCUnicode_pyobjc_NSString, METH_NOARGS, "directly access NSString instance" }, { 0, 0, 0, 0 } /* sentinel */ }; PyTypeObject ObjCUnicode_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, /* ob_size */ "objc.pyobjc_unicode", /* tp_name */ 0, /* tp_basicsize */ sizeof(ObjCUnicodeObject), /* tp_itemsize */ /* methods */ class_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ class_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ class_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &PyUnicode_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0, /* tp_free */ }; /* TODO: Use proper access macros to access UnicodeObject fields */ PyObject* ObjCUnicode_New(NSString* value) { const char* utf8 = [value UTF8String]; PyUnicodeObject* tmp = (PyUnicodeObject*)PyUnicode_DecodeUTF8(utf8, strlen(utf8), "strict"); ObjCUnicodeObject* result; if (tmp == NULL) return NULL; result = PyObject_New(ObjCUnicodeObject, &ObjCUnicode_Type); result->base.str = PyMem_NEW(Py_UNICODE, tmp->length); if (result->base.str == NULL) { Py_DECREF((PyObject*)result); PyErr_NoMemory(); return NULL; } result->base.length = tmp->length; memcpy(result->base.str, tmp->str, sizeof(tmp->str[0]) * tmp->length); Py_DECREF(tmp); result->weakrefs = 0; result->nsstr = [value retain]; return result; } NSString* ObjCUnicode_Extract(PyObject* value) { if (!ObjCUnicode_Check(value)) { PyErr_BadInternalCall(); return NULL; } return ((ObjCUnicodeObject*)value)->nsstr; } |