I am calling an externally provided COM DLL for which I have generated a COM interop wrapper. For the sake of argument, let's call the interface I want to call IEnumFoo
.
IEnumFoo
has the typical COM enumerator pattern:
HRESULT Next (
ULONG celt,
IFoo** rgelt,
ULONG* pceltFetched
);
where the first parameter is the number of desired results, the second parameter is a buffer to which results are written, and the last parameter describes the number of results actually written.
When I choose "Add Reference" and point Visual Studio at this DLL, it generates a COM Interop Assembly with the following signature:
void Next(uint, out IFoo, out uint)
This only allows the .NET code to request a single object at a time, which can add a significant amount of overhead to using these APIs.
Is there some mechanism I can use to generate a version of Next
which would allow me to provide more IFoo
"slots" above which would make the marshaler happy? (I'm not averse to editing the IL in the interop assembly by hand :) )
The proper signature for this would be like so:
void Next(
uint celt,
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] IFoo[] rgelt,
out uint pceltFetched);
According to MSDN, at least, there's no mechanism to generate this automatically. Even if the original IDL for the interface had length_is
applied to rgelt
, that information is lost in the typelib. So you'll need to edit the interop assembly manually.
One other option is to define this particular interface entirely by hand in your main assembly, and simply ignore the generated interop version. Remember that when doing casts on RCWs, any interface with a matching GUID (i.e. the one for which QueryInterface is successful) will work, so you can actually have several different managed interfaces that present differing views of the same COM interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With