Re: [Python-Dev] Feature request: better support for "wrapper" objects
Recently, "Martin v. Loewis"
Now I've looked somewhat throught the Python source, and found Mac/Modules/Win/_Winmodule.c:WinObj_SetWindowModality (taking an arbitrary that seemed to match your description of "Windows"). Is that one of the examples you were referring to? If so, I still cannot understand the example. It reads
if (!PyArg_ParseTuple(_args, "lO&", &inModalKind, WinObj_Convert, &inUnavailableWindow))
so it appears that you would like to rewrite this as
if (!PyArg_ParseTuple(_args, "lO@", &inModalKind, WinObj_Type, &inUnavailableWindow))
Now, if that is how it is supposed to look like: How exactly would it work? WinObj_Convert accepts None, integers, and WinObjs. It seems that the rewritten version would only accept WinObj objects.
Basically correct, but there is no reason why the rewritten version would accept only WinObj's. ("O@", typeobj, ptr) would call typeobj->tp_convert(arg[i], ptr) and the semantics of tp_convert would be '"cast" arg PyObject to whatever your type is and store the C pointer value for that thing in ptr'. Or, to make things clearer, WinObj_Type->tp_convert would simply point to the current WinObj_Convert function.
If we had something like ("O@", typeobject) calldll could be extended so you could do something like psapilib = calldll.getlibrary(....) ps_GetDrawableSurface = calldll.newcall(psapilib.ps_GetDrawableSurface, Carbon.Qd.GrafPortType)
(newcall() arguments are funcpointer, return value type, arg1 type, ...)
You cannot do this currently
Please let me try to summarize what this is doing: Given a type object and a long, create an instance of that type. Is that a correct analysis of what has to be done?
That would allow you to do the same thing, but rather more error prone (i.e. I think it is much more of a hack than what I'm trying to get at). As you noted above WinObj's unfortunately need such a hack, but I would expect to get rid of it as soon as possible. I really don't like passing C pointers around in Python integers.
I completely fail to see how O& fits into the puzzle. AFAICT, conversion of the return value occurs inside cdc_call. There is no tuple to parse anyway nearby.
Not at the moment, but in calldll version 2 there would be. In stead
of passing types as "l" or "h" you would pass type objects to
newcall(). Newcall() would probably special-case the various ints but
for all other types simply call PyArg_Parse(arg, "O@", typeobj,
&voidptr).
--
- Jack Jansen
Or, to make things clearer, WinObj_Type->tp_convert would simply point to the current WinObj_Convert function.
So what do you gain with that extension? It seem all that is done is you can replace _Convert by _Type everywhere, with no additional change to the semantics.
ps_GetDrawableSurface = calldll.newcall(psapilib.ps_GetDrawableSurface, Carbon.Qd.GrafPortType) [...] Not at the moment, but in calldll version 2 there would be. In stead of passing types as "l" or "h" you would pass type objects to newcall(). Newcall() would probably special-case the various ints but for all other types simply call PyArg_Parse(arg, "O@", typeobj, &voidptr).
I still don't understand. In your example, GrafPortType is a return type, not an argument type. So you *have* an anything, and you *want* the GrafPortType. How exactly do you use PyArg_Parse in that scenario? Also, why would you use this extension inside newcall()? I'd rather expect it in ps_GetDrawableSurface.__call__ instead (i.e. when you deal with a specific call, not when you create the callable instance). Regards, Martin
If we had something like ("O@", typeobject) calldll could be extended so you could do something like psapilib = calldll.getlibrary(....) ps_GetDrawableSurface = calldll.newcall(psapilib.ps_GetDrawableSurface, Carbon.Qd.GrafPortType)
(newcall() arguments are funcpointer, return value type, arg1 type, ...)
You cannot do this currently
Please let me try to summarize what this is doing: Given a type object and a long, create an instance of that type. Is that a correct analysis of what has to be done?
That would allow you to do the same thing, but rather more error prone (i.e. I think it is much more of a hack than what I'm trying to get at). As you noted above WinObj's unfortunately need such a hack, but I would expect to get rid of it as soon as possible. I really don't like passing C pointers around in Python integers.
I completely fail to see how O& fits into the puzzle. AFAICT, conversion of the return value occurs inside cdc_call. There is no tuple to parse anyway nearby.
Not at the moment, but in calldll version 2 there would be. In stead of passing types as "l" or "h" you would pass type objects to newcall(). Newcall() would probably special-case the various ints but for all other types simply call PyArg_Parse(arg, "O@", typeobj, &voidptr).
Here's an outline which could work in 2.2: Create a subtype of type, having a tp_convert slot: typedef int (*convert_func)(PyTypeObject *, void **); typedef struct { PyTypeObject type; convert_func tp_convert; } WrapperTypeType; and use it as metaclass (metatype?) for your WindowObj: class WindowObj(...): __metaclass__ = WrapperTypeType Write a function to return a conversion function: convert_func *get_converter(PyTypeObject *type) { if (WrapperTypeType_Check(type)) return ((WrapperTypeType *)type)->tp_convert; /* code to check additional types and return their converters */ .... } and then if (!PyArg_ParseTuple(args, "O&", get_converter(WinObj_Type), &Window)) How does this sound? Thomas
participants (3)
-
Jack Jansen
-
Martin v. Loewis
-
Thomas Heller