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 _______________________________________________ Python-win32 mailing list Python-win32@python.org http://mail.python.org/mailman/listinfo/python-win32