Ronald Oussoren avatar Ronald Oussoren committed 4b86046

Various fixes for ObCPointer

* Type wasn't exposed in module objc

* Couldn't introspect the type

* Couldn't access attributes of instances

* Removed aPointer.unwrap()

* aPointer.type is now the encoding of the pointer type,
not of the pointed to value

* Don't raise an exception instead of creating
an ObjCPointer value (that option will be default to on in 3.1)

* Add tests for the ObjCPointer type

Comments (0)

Files changed (8)

pyobjc-core/Doc/api/module-objc.rst

    .. data:: pointerAsInteger
 
       An integer value with the raw pointer value.
-
-   .. method:: unpack()
-
-      Returns a python representation of the pointed-to value.

pyobjc-core/Modules/objc/ObjCPointer.m

 
 typedef struct
 {
-    PyObject_VAR_HEAD
+    PyObject_HEAD
 
     void *ptr;
     PyObject *type;
-    char contents[1];
 } PyObjCPointer;
 
 
     PyObject_Free((PyObject*)self);
 }
 
-PyDoc_STRVAR(PyObjCPointer_unpack_doc,
-    "Unpack the pointed value accordingly to its type.\n"
-    "obj.unpack() -> value");
-
-static PyObject *
-PyObjCPointer_unpack (PyObject* _self)
-{
-    PyObjCPointer* self = (PyObjCPointer*)_self;
-
-    if (PyErr_WarnEx(
-        PyExc_DeprecationWarning,
-            "Using ObjCPointer is deprecated, unpack will be removed in PyObjC 3.1",
-            1) < 0) {
-
-        return NULL;
-    }
-
-    if (self->ptr) {
-        const char *type = PyBytes_AS_STRING(self->type);
-
-        if (*type == _C_VOID) {
-            PyErr_SetString (PyObjCExc_Error,
-                "Cannot dereference a pointer to void");
-            return NULL;
-        } else {
-            return pythonify_c_value(type, self->ptr);
-        }
-    } else {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-}
-
-static PyMethodDef PyObjCPointer_methods[] =
-{
-    {
-        "unpack",
-        (PyCFunction)PyObjCPointer_unpack,
-        METH_NOARGS,
-        PyObjCPointer_unpack_doc
-    },
-    { 0, 0, 0, 0 }
-};
-
 static PyMemberDef PyObjCPointer_members[] = {
     {
         "type",
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     .tp_name        = "PyObjCPointer",
     .tp_basicsize   = sizeof (PyObjCPointer),
-    .tp_itemsize    = sizeof (char),
+    .tp_itemsize    = 0,
     .tp_dealloc     = PyObjCPointer_dealloc,
+    .tp_getattro    = PyObject_GenericGetAttr,
     .tp_flags       = Py_TPFLAGS_DEFAULT,
     .tp_doc         = "Wrapper around a Objective-C Pointer",
-    .tp_methods     = PyObjCPointer_methods,
     .tp_members     = PyObjCPointer_members,
 };
 
 {
     Py_ssize_t size = PyObjCRT_SizeOfType (t);
     const char *typeend = PyObjCRT_SkipTypeSpec (t);
+    while (isdigit(typeend[-1])) {
+        typeend --;
+    }
     PyObjCPointer *self;
 
     if (PyObjCPointer_RaiseException) {
         return NULL;
     }
 
-    self = PyObject_NEW_VAR(PyObjCPointer, &PyObjCPointer_Type, size);
+    self = PyObject_NEW(PyObjCPointer, &PyObjCPointer_Type);
     if (self == NULL) {
         return NULL;
     }
 
     self->type = PyBytes_FromStringAndSize ((char *) t, typeend-t);
-
-    if (size && p) {
-        memcpy ((self->ptr = self->contents), p, size);
-    } else {
-        self->ptr = p;
-    }
+    self->ptr = p;
 
     return (PyObject*)self;
 }

pyobjc-core/Modules/objc/module.m

         PyObjC_INITERROR();
     }
 
+    if (PyType_Ready(&PyObjCPointer_Type) < 0) {
+        PyObjC_INITERROR();
+    }
     if (PyType_Ready(&PyObjCMetaClass_Type) < 0) {
         PyObjC_INITERROR();
     }
         PyObjC_INITERROR();
     }
 
+    if (PyDict_SetItemString(d, "ObjCPointer", (PyObject*)&PyObjCPointer_Type) < 0) {
+        PyObjC_INITERROR();
+    }
     if (PyDict_SetItemString(d, "objc_meta_class", (PyObject*)&PyObjCMetaClass_Type) < 0) {
         PyObjC_INITERROR();
     }

pyobjc-core/Modules/objc/objc_support.m

             retobject = PyObjCPointerWrapper_ToPython(type, datum);
             if (retobject == NULL && !PyErr_Occurred()) {
                 retobject = (PyObject*)PyObjCPointer_New(
-                    *(void**) datum, type+1);
+                    *(void**) datum, type);
             }
         }
         break;

pyobjc-core/Modules/objc/options.m

 /* Public properties */
 BOOL_PROP(verbose, PyObjC_Verbose, NO)
 BOOL_PROP(use_kvo, PyObjC_UseKVO, YES)
-BOOL_PROP(unknown_pointer_raises, PyObjCPointer_RaiseException, YES)
+BOOL_PROP(unknown_pointer_raises, PyObjCPointer_RaiseException, NO)
 
 #if PY_MAJOR_VERSION == 2
 BOOL_PROP(strbridge_enabled, PyObjC_StrBridgeEnabled, YES)

pyobjc-core/Modules/objc/test/structpointer1.m

     int i1;
 };
 
+struct UnwrappedStruct {
+    int i1;
+    int i2;
+};
+
 static struct TestStructPointerStruct myGlobal = { 1 };
 
 @interface OC_TestStructPointer : NSObject
 {
 }
 +(struct TestStructPointerStruct*)returnPointerToStruct;
++(struct UnwrappedStruct*)returnUnwrapped;
 @end
 
 @implementation OC_TestStructPointer
 {
     return &myGlobal;
 }
+
++(struct UnwrappedStruct*)returnUnwrapped
+{
+    return (struct UnwrappedStruct*)42;
+}
+
 @end
 
 

pyobjc-core/NEWS.txt

 * PyObjC 3 requires a compiler that supports Objective-C with C99 as the base
   language.
 
-* PyObjC will now raise an exception instead of creating instances of
-  :class:`objc.PyObjCPointer`. You can set :data:`objc.options.unknown_pointer_raises`
-  to False to re-enable the previous behavior (although that is almost always the
-  wrong solution).
+* PyObjC raises an exception instead of creating instances of
+  :class:`objc.PyObjCPointer` when you set :data:`objc.options.unknown_pointer_raises`
+  to :data:`True`.
+
+  The default is currently :data:`False`, that will be changed in a future version
+  and the entire `objc.ObjCPointer` class will likely be removed some releases
+  after that.
 
 * Configuration options are now attributes of special object :data:`objc.options`.
 
 
 * ``del aSelector.isHidden`` crashed the interpreter (see above)
 
+* Class :class:`objc.ObjCPointer` was not exposed in the :mod:`objc` module.
+
+* The implementation of :class:`objc.ObjCPointer` didn't have a proper
+  implementation of *__getattribute__* and that made objects of this
+  class even more useless than they should have been.
+
+* Values of :class:`objc.ObjCPointer` no longer have an unpack method
+  (the method has been inaccisible for several releases and its implementation
+  as unsafe)
+
+* The *type* attribute of :class:`objc.ObjCPointer` now starts with
+  :data:`objc._C_PTR` (that is, the *type* attribute is the encoded type
+  of the pointer, instead of the encoded type of the pointed-to value).
+
 Version 2.6
 -----------
 

pyobjc-core/TODO.txt

   module, otherwise core has the expose too much functionality
   (especially when enhancing the test suite)
 
+  Use Py_FindMethod for this:
+     PyObject* Py_FindMethod(PyMethodDef table[], PyObject *ob, char *name)
+
 * tests with blocks that return a large struct (stret calling convention)
 
 * Is it possible to implement pyobjc_unicode in Python?
     In both cases check that the method can be called (both directly
     and through super)
 
+
+* JavsaScriptCore bindings need work (missing opaque pointer types, no tests, no examples, ...)
+
+* Add tests for objc.ObjCPointer (creating, introspection, accessing value, accessing pointer)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.