Объявление открытого массива потеряно при повторном создании interop.dll с помощью tlbimp.exe из type-lib

Мне нужно восстановить interop.dll из библиотеки типов. Поэтому я загорелся

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

Но в отличии от оригинального interop.dll я узнал с помощью обозревателя объектов (см. ниже)

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

что открытый массив для метода-параметра для SetNodeArr потерян:

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

Я пробовал некоторые варианты TlbImp.exe, но безуспешно.

Вопрос Какую настройку мне нужно сделать, чтобы параметр pArray был объявлен как открытый массив вместо простой ссылки?


person participant    schedule 09.06.2015    source источник


Ответы (1)


Это вполне обычное несчастье. Вы можете увидеть основную проблему, запустив OleView.exe из командной строки Visual Studio. Используйте File + View Typelib и выберите .tlb. Вы должны увидеть что-то вроде:

   void SetNodeArr(int Size, FOO_NODE* pArray); 

Указатель - проблема, он неоднозначен. Это может означать, что аргумент является массивом, или это может означать, что это структура, которая передается по ссылке.

Вы увидите подобные объявления для COM-серверов, предназначенных для использования в программах на C или C++. Тип языка, в котором массив распадается на указатель на первый элемент, когда он передается в качестве аргумента.

Это не работает в языках, которые обрабатывают массивы как объекты, например в языках .NET. Дружественный COM-сервер, поддерживающий множество различных языков, вместо этого объявит этот аргумент как SAFEARRAY. Теперь однозначно, каким может быть тип аргумента, это всегда массив. Аргумент Size также не нужен, безопасный массив знает свой собственный размер. Это объект.

Таким образом, у Tlbimp.exe нет шансов угадать правильный перевод, он всегда указывает на struct-passed-by-reference, самый безопасный выбор. Таким образом ref FOO_NODE. Вы ничего не можете сделать, чтобы сделать это мудрее, когда вы застряли в способе реализации COM-сервера.

Исправление библиотеки взаимодействия возможно, процедура описана в Библиотека MSDN. Декомпилируйте сборку с помощью ildasm.exe, отредактируйте IL, чтобы исправить объявление (попробуйте сначала с образцом кода C#, чтобы увидеть, как это должно выглядеть), снова соберите шалтай-болтай с помощью ilasm.exe.

person Hans Passant    schedule 09.06.2015