Index: ctypes/test/test_parameters.py =================================================================== RCS file: /cvsroot/ctypes/ctypes/ctypes/test/test_parameters.py,v retrieving revision 1.3 diff -u -r1.3 test_parameters.py --- ctypes/test/test_parameters.py 14 Mar 2006 19:09:21 -0000 1.3 +++ ctypes/test/test_parameters.py 5 Jul 2006 20:16:37 -0000 @@ -147,6 +147,41 @@ ## 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__': Index: docs/manual/reference.txt =================================================================== RCS file: /cvsroot/ctypes/ctypes/docs/manual/reference.txt,v retrieving revision 1.43 diff -u -r1.43 reference.txt --- docs/manual/reference.txt 3 Jul 2006 14:29:12 -0000 1.43 +++ docs/manual/reference.txt 5 Jul 2006 20:20:15 -0000 @@ -231,6 +231,12 @@ convert a unicode string passed as argument into an byte string using ctypes conversion rules. + New: It is now possible to put items in argtypes which are not + ctypes types, but each item must have a ``from_param`` method + which returns a value usable as argument (integer, string, ctypes + instance). This allows to define adapters that can adapt custom + objects as function parameters. + ``errcheck`` : memberdesc Assign a Python function or another callable to this attribute. The callable will be called with three or more arguments: Index: source/_ctypes.c =================================================================== RCS file: /cvsroot/ctypes/ctypes/source/_ctypes.c,v retrieving revision 1.341 diff -u -r1.341 _ctypes.c --- source/_ctypes.c 5 Jul 2006 08:32:33 -0000 1.341 +++ source/_ctypes.c 5 Jul 2006 20:01:59 -0000 @@ -1633,9 +1633,8 @@ 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); } @@ -1646,7 +1645,7 @@ 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; }