Open array declaration lost when regenerating interop.dll with tlbimp.exe from type-lib

521 views Asked by At

I need to regenerate the interop.dll from a type-library. Therefore I fired up

TlbImp.exe" foo.tlb /out:interop.dll

But in contrast to the original interop.dll, I found out with the object browser (see below)

void SetNodeArr(int Size, FOO_NODE[] pArray)       // original interop.dll

that the open array for the method-parameter for SetNodeArr is lost:

void SetNodeArr(int Size, ref FOO_NODE pArray)     // regenrated interop.dll

I've tried some of the options of TlbImp.exe, but with no luck.

Q What tweak do I need to get parameter pArray declared as an open array instead of a simple reference?

1

There are 1 answers

0
Hans Passant On BEST ANSWER

This is a pretty normal mishap. You can see the underlying problem by running OleView.exe from the Visual Studio Command Prompt. Use File + View Typelib and select the .tlb. You should see something like:

   void SetNodeArr(int Size, FOO_NODE* pArray); 

The pointer is the problem, it is ambiguous. It could mean that the argument is an array or it could mean that it is a struct that's passed by reference.

You'd see declarations like this for COM servers that were designed to be used from a C or C++ program. The kind of language where an array decays to a pointer to the first element when it is passed as an argument.

That cannot work in languages that treat arrays as objects, like the .NET languages. A friendly COM server that supports many different kind of languages will declare this argument as a SAFEARRAY instead. Now it is unambiguous what the type of the argument can be, that's always an array. Does not need the Size argument either, a safe array knows its own size. It is an object.

So Tlbimp.exe doesn't stand a chance to guess at the proper translation, it always punts for struct-passed-by-reference, the safest choice. Thus ref FOO_NODE. There isn't anything you can do to make it any wiser about it either when you are stuck with the way the COM server is implemented.

Fixing the interop library is possible, the procedure is described in the MSDN library. Decompile the assembly with ildasm.exe, edit the IL to fix the declaration (try it first with sample C# code to see what it should look like), put humpty-dumpty back together again with ilasm.exe