[python-win32] Explicit variant types for Invoke & InvokeTypes (WasRe: Autocad.*)
Dan Glassman
dan.glassman at charter.net
Wed Feb 8 23:01:15 CET 2006
Mark Hammond wrote:
>> if ( PySequence_Check(obuse) )
>> {
>> V_ARRAY(var) = NULL; // not a valid, existing array.
>> ok = PyCom_SAFEARRAYFromPyObject(obuse, &V_ARRAY(var), rawVT);
>> V_VT(var) = VT_ARRAY | rawVT;
>> }
>> else
>> {
>> PythonOleArgHelper helper;
>> helper.m_reqdType = rawVT;
>> V_VT(var) = rawVT;
>> ok = helper.MakeObjToVariant(obuse, var);
>
> The problem may well be your use of PySequence_Check() - that will succeed
> for a string. You are then likely to end up with a VT_UI8 array. I think
> you should *always* defer to MakeObjToVariant - that function will check the
> VT, and if an array is requested it will do the right thing - ie, the
> variant-type should *always* drive the conversion process in this case,
> rather than the object value.
Ah -- the lightbulb above my head is now lit. Thank you!
> Yep, I think this is looking quite reasonable. Regarding testing, the best
> thing is probably to try and use win32com\test\testvb.py. If you have VB
> and the pywin32 sources, you should be able to create the test DLL from the
> com\TestSources\PyCOMVBTest directory. testvb.py exercises *lots* of
> different variant types, so somehow arranging (by copy-paste if necessary)
> for those tests to be called with a new Variant object would be excellent.
> If you don't have VB, let me know and I will send you a compliled DLL.
Got the tests, passed the tests! The original testvb.py also passes, so
I can't have messed anything up *too* much! :)
I don't want to post such long code, so I'm hosting it. If the links
don't work for any interested party, please just email me and I'll get
you a copy. I'm quite enjoying this learning experience and am open to
all suggestions.
Test file:
http://www.originalrog.org/testvb_variantclass.py
My first try at class Variant (and some helpers):
http://www.originalrog.org/VariantUtils.py
That is the class definition which passed the tests. I hope a new-style
class is okay; I figured it would be, given the python versions for
which pywin32 "binaries" are distributed. If not, I don't think there's
anything that can't be rewritten in classic style.
A brief interactive session showing some class behaviour:
http://www.originalrog.org/variantclass_interactive.txt
The C++ implementation is below. I erased some of this
thread...so...context: this is in oleargs.cpp in
PyCom_VariantFromPyObject(). I put this clause just before the
PySequence_Check() clause instead of at the top; figure it won't be used
as often as the other clauses.
[code]
else if (strcmp(obj->ob_type->ob_type->tp_name, "VariantBase") == 0)
{
PyObject* typeAttr = PyString_FromString("_com_variant_type_");
PyObject* valAttr = PyString_FromString("_com_variant_value_");
if (!(typeAttr && valAttr))
return FALSE;
PyObject* reqdType = PyObject_GenericGetAttr(obj, typeAttr);
if (!reqdType)
return FALSE;
VARENUM rawVT = (VARENUM)PyInt_AsLong(reqdType);
PyObject* obuse = PyObject_GenericGetAttr(obj, valAttr);
if (!obuse)
{
Py_XDECREF(reqdType);
return FALSE;
}
PythonOleArgHelper helper;
helper.m_reqdType = V_VT(var) = rawVT;
helper.MakeObjToVariant(obuse, var);
Py_XDECREF(reqdType);
Py_XDECREF(obuse);
}
// NOTE: PySequence_Check may return true for instance objects,
...
[/code]
Cheers!
-Dan Glassman
More information about the Python-win32
mailing list