def testBufferProtocol(self, mapper, later): # should all be implemented in C really, but weaving cpy string type into # our code feels too much like hard work for now strPtr = mapper.PyString_Type bufPtr = CPyMarshal.ReadPtrField(strPtr, PyTypeObject, 'tp_as_buffer') self.assertNotEquals(bufPtr, IntPtr.Zero) getreadbuffer = CPyMarshal.ReadFunctionPtrField( bufPtr, PyBufferProcs, 'bf_getreadbuffer', dgt_int_ptrintptr) getwritebuffer = CPyMarshal.ReadFunctionPtrField( bufPtr, PyBufferProcs, 'bf_getwritebuffer', dgt_int_ptrintptr) getcharbuffer = CPyMarshal.ReadFunctionPtrField( bufPtr, PyBufferProcs, 'bf_getcharbuffer', dgt_int_ptrintptr) getsegcount = CPyMarshal.ReadFunctionPtrField(bufPtr, PyBufferProcs, 'bf_getsegcount', dgt_int_ptrptr) ptrptr = Marshal.AllocHGlobal(Marshal.SizeOf(IntPtr)) later(lambda: Marshal.FreeHGlobal(ptrptr)) strptr = mapper.Store("hullo") for getter in (getreadbuffer, getcharbuffer): self.assertEquals(getter(strptr, 0, ptrptr), 5) self.assertEquals( CPyMarshal.ReadPtr(ptrptr), CPyMarshal.GetField(strptr, PyStringObject, 'ob_sval')) self.assertEquals(getter(strptr, 1, ptrptr), -1) self.assertMapperHasError(mapper, SystemError) self.assertEquals(getwritebuffer(strptr, 0, ptrptr), -1) self.assertMapperHasError(mapper, SystemError) self.assertEquals(getsegcount(strptr, ptrptr), 1) self.assertEquals(CPyMarshal.ReadInt(ptrptr), 5) self.assertEquals(getsegcount(strptr, IntPtr.Zero), 1)
def assertTypeDeallocWorks(self, typename, CreateMapper, CreateInstance, TestConsequences): mapper = CreateMapper() deallocTypes = CreateTypes(mapper) calls = [] def tp_free(ptr): calls.append(("tp_free", ptr)) self.tp_freeDgt = dgt_void_ptr(tp_free) CPyMarshal.WriteFunctionPtrField(getattr(mapper, typename), PyTypeObject, "tp_free", self.tp_freeDgt) objPtr = CreateInstance(mapper, calls) deallocDgt = CPyMarshal.ReadFunctionPtrField(getattr(mapper, typename), PyTypeObject, "tp_dealloc", dgt_void_ptr) deallocDgt(objPtr) TestConsequences(mapper, objPtr, calls) mapper.Dispose() deallocTypes()
def testIC_PyType_Type_tp_new(self, mapper, _): IC_PyType_New = CPyMarshal.ReadFunctionPtrField(mapper.PyType_Type, PyTypeObject, "tp_new", dgt_ptr_ptrptrptr) typeArgs = ("hello", (float,), {'cheese': 27}) # we have only ever seen this called from *within* a metatype's tp_new; # therefore, we claim that its intent is to contruct a vanilla type, and # that any metaclass-notification stuff should be handled by the caller. # therefore, we can ignore the first arg and always pretend it's PyType_Type. # handwave handwave; hey, look, a three-headed monkey! typePtr = IC_PyType_New(IntPtr.Zero, mapper.Store(typeArgs), IntPtr.Zero) type_ = mapper.Retrieve(typePtr) self.assertEquals(type_.__name__, "hello") self.assertEquals(issubclass(type_, float), True) self.assertEquals(type_.cheese, 27)
def testPyListTypeField_tp_dealloc(self): calls = [] class MyPM(PythonMapper): def IC_PyList_Dealloc(self, listPtr): calls.append(listPtr) mapper = MyPM() typeBlock = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject)) mapper.RegisterData("PyList_Type", typeBlock) gcwait() # this will make the function pointers invalid if we forgot to store references to the delegates deallocDgt = CPyMarshal.ReadFunctionPtrField(typeBlock, PyTypeObject, "tp_dealloc", dgt_void_ptr) deallocDgt(IntPtr(12345)) self.assertEquals(calls, [IntPtr(12345)], "wrong calls") mapper.Dispose() Marshal.FreeHGlobal(typeBlock)
def testReadFunctionPtrField(self): data = Marshal.AllocHGlobal(Marshal.SizeOf(PyTypeObject())) CPyMarshal.Zero(data, Marshal.SizeOf(PyTypeObject())) calls = [] def TestFunc(selfPtr, argsPtr, kwargsPtr): calls.append((selfPtr, argsPtr, kwargsPtr)) return 123 self.testDgt = dgt_int_ptrptrptr(TestFunc) CPyMarshal.WriteFunctionPtrField(data, PyTypeObject, "tp_init", self.testDgt) readDgt = CPyMarshal.ReadFunctionPtrField(data, PyTypeObject, "tp_init", dgt_int_ptrptrptr) args = (IntPtr(111), IntPtr(222), IntPtr(333)) self.assertEquals(readDgt(*args), 123, "not hooked up") self.assertEquals(calls, [args], "not hooked up")
def testPyFloat_UnManagedNew(self, mapper, _): tp_new = CPyMarshal.ReadFunctionPtrField(mapper.PyFloat_Type, PyTypeObject, "tp_new", dgt_ptr_ptrptrptr) for value in (0, 1, 1.5, "1.0"): unmanaged_float = tp_new(mapper.PyFloat_Type, mapper.Store((value, )), IntPtr.Zero) actualType = CPyMarshal.ReadPtrField(unmanaged_float, PyObject, "ob_type") self.assertEquals(actualType, mapper.PyFloat_Type) self.assertEquals(mapper.Retrieve(unmanaged_float), float(value)) for bad_value in ("hello", object(), object): unmanaged_float = tp_new(mapper.PyFloat_Type, mapper.Store((bad_value, )), IntPtr.Zero) self.assertEquals(unmanaged_float, IntPtr.Zero) error = None try: float(bad_value) except Exception, e: error = type(e) self.assertMapperHasError(mapper, error)
def testIC_PyDict_Init(self, mapper, _): IC_PyDict_Init = CPyMarshal.ReadFunctionPtrField( mapper.PyDict_Type, PyTypeObject, "tp_init", dgt_int_ptrptrptr) # really, this function does *nothing*. and certainly doesn't follow the pointers passed in self.assertEquals( IC_PyDict_Init(IntPtr(123), IntPtr(456), IntPtr(789)), 0)