I got no response to this in microsoft.public.dotnet.framework.interop,
and since it is a C++-related problem, I am now trying it here:
I am using an Interop assembly for communication between my Managed C++
application and an ATL-based COM server. The Interop assembly was
created with Visual Studio, and the COM server is third-party software
that is not under my control.
One of the COM interfaces supported by the server has a method defined
like this:
HRESULT Func(
[out] VARIANT* bunchOfIntegers,
[out] VARIANT* bunchOfStrings);
(the actual function has a lot more parameters, but I have tried to
strip the example down to the necessary minimum).
The VARIANT bunchOfIntegers is documented as SAFEARRAY VT_I4, VT_BYREF,
while bunchOfStrings is actually a SAFEARRAY VT_BSTR, VT_BYREF, with the
added twist that it's a two-dimensional array. The caller is supposed to
pass these arrays which are then filled by the server.
The corresponding member function in the Interop assembly's wrapper
class is described by the object browser as
public virtual void Func (out object bunchOfIntegers,
out object bunchOfStrings);
A couple of minutes of intensive conversation with the compiler
convinced my that the corresponding C++ function prototype is
virtual void Func (System::Object __gc* __gc* bunchOfIntegers,
System::Object __gc* __gc* bunchOfStrings);
(why does the IDE not provide me with this information, by the way?)
The function documentation says that null pointers may be used to
suppress information selectively. Going for the simpler data structure
first, I eventually arrived at something along the lines of:
// count is already known at this point
int bunchOfIntegers __gc [] = new int __gc [count];
Object* bunchOfIntegersObject = bunchOfIntegers;
Object* bunchOfStringsObject = 0;
Func (&bunchOfIntegersObject, &bunchOfStringsObject);
While this code gives me the creeps (taking addresses of managed
pointers?!), it was the only form that placated the compiler. Now comes
the really weird thing. When I executed Func in the debugger,
bunchOfIntegers was untouched, but bunchOfStringsObject referred to an
allocated two-dimensional array with meaningful values returned by Func!
In other words, allocating an array did not work, but passing the
address of a managed null pointer did. Can anyone explain this? And can
anyone tell me whether these scary contortions are the correct way of
obtaining values for the described VARIANT out parameters?
--
Gerhard Menzl
Humans may reply by replacing the obviously faked part of my e-mail
address with "kapsch".