## def test_performance(self):
## check_perf()
+ def test_noctypes_argtype(self):
+ import _ctypes_test
+ from ctypes import CDLL, c_void_p, ArgumentError
+
+ func = CDLL(_ctypes_test.__file__)._testfunc_p_p
+ func.restype = c_void_p
+ # TypeError: has no from_param method
+ self.assertRaises(TypeError, setattr, func, "argtypes", (object,))
+
+ class Adapter(object):
+ def from_param(cls, obj):
+ return None
+
+ func.argtypes = (Adapter(),)
+ self.failUnlessEqual(func(None), None)
+ self.failUnlessEqual(func(object()), None)
+
+ class Adapter(object):
+ def from_param(cls, obj):
+ return obj
+
+ func.argtypes = (Adapter(),)
+ # don't know how to convert parameter 1
+ self.assertRaises(ArgumentError, func, object())
+ self.failUnlessEqual(func(c_void_p(42)), 42)
+
+ class Adapter(object):
+ def from_param(cls, obj):
+ raise ValueError(obj)
+
+ func.argtypes = (Adapter(),)
+ # ArgumentError: argument 1: ValueError: 99
+ self.assertRaises(ArgumentError, func, 99)
+
+
################################################################
if __name__ == '__main__':
Library
-------
+- Patch #1517790: It is now possible to use custom objects in the ctypes
+ foreign function argtypes sequence as long as they provide a from_param
+ method, no longer is it required that the object is a ctypes type.
+
- string.Template() now correctly handles tuple-values. Previously,
multi-value tuples would raise an exception and single-value tuples would
be treated as the value they contain, instead.
for (i = 0; i < nArgs; ++i) {
PyObject *tp = PyTuple_GET_ITEM(ob, i);
- StgDictObject *dict = PyType_stgdict(tp);
PyObject *cnv = PyObject_GetAttrString(tp, "from_param");
- if (!dict || !cnv)
+ if (!cnv)
goto argtypes_error_1;
PyTuple_SET_ITEM(converters, i, cnv);
}
Py_XDECREF(converters);
Py_DECREF(ob);
PyErr_Format(PyExc_TypeError,
- "item %d in _argtypes_ is not a valid C type", i+1);
+ "item %d in _argtypes_ has no from_param method", i+1);
return NULL;
}