Как лучше всего избегать двойного преобразования в нативных типах C++/CLI
Традиционно я использую расширение MFC dll и импортирую / экспортирую, используя dllimport / dllexport.
Однако, когда dll изменяется на использование /clr, этот метод становится дорогостоящим, так как вызовы могут привести к двойной передаче. Я сейчас получаю огромный удар по производительности, и мне нужно прекратить двойные действия. Описанное мною решение предлагает убедиться, что все использует соглашение __clrcall, но это не работает с dllexport.
Собственный раздел Microsoft о двойном понимании предлагает:
Аналогично, если вы экспортируете (dllexport, dllimport) управляемую функцию, генерируется собственная точка входа, и любая функция, которая импортирует и вызывает эту функцию, будет вызывать через собственную точку входа. Чтобы избежать двойного подхода в этой ситуации, не используйте собственную семантику экспорта / импорта; просто ссылайтесь на метаданные через #using (см. директиву #using (C++)).
Для меня это выглядит так, как будто я могу удалить dllexport/dllimport из моих классов и вставить #using в мой stdafx.h. Однако для нативных типов это приводит к LNK2028 (неразрешенный токен) и LNK2019 (неразрешенный внешний символ). Не имеет значения, включаю ли я.lib в компоновщик или нет; Я все еще получаю эту ошибку.
Итак, мой вопрос: как лучше избежать двойного объединения и импортировать нативные типы из библиотеки C++/CLI?
С уважением
Ник
** ОБНОВИТЬ **
Некоторые обновления из тестирования.
Как только dll скомпилирована с /clr, двойное преобразование происходит для нативных типов (используя dllexport/dllimport).
Этого можно избежать, отключив поддержку CLR для каждого файла отдельно. Это боль, и иногда нативные типы используют clr, так что это нельзя сделать везде. И вызываемый должен быть скомпилирован нативно, чтобы он работал.
Методы могут быть помечены __clrcall, но это приведет к ошибке компиляции при смешивании с dllexport. Тем не менее, мне удалось заставить следующий код работать без двойного кода:
// MFCCLRLIB_API is defined in the library only (as dllexport) // but NOT defined when using (dllimport) // MFCCLRLIB_CALL is defined as empty in the library, // but __clrcall when using. #ifndef _MFCCLRLIB #define MFCCLRLIB_API #define MFCCLRLIB_CALL __clrcall #endif class MFCCLRLIB_API ThunkHack { public: ThunkHack(); ThunkHack(const ThunkHack&); ~ThunkHack(); }; class MFCCLRLIB_API ThunkHackCaller { public: ThunkHackCaller(void); ~ThunkHackCaller(void); virtual void MFCCLRLIB_CALL UseThunkClass(ThunkHack thunk); };
Это компилирует, и я могу теперь использовать класс вызывающей стороны вне библиотеки, и это не приводит к двойному потоку. Что я и хочу. Я обеспокоен, однако, что это не способ сделать это; Я не читал ничего, что предполагает, что этот подход безопасен.
Мне бы очень хотелось получить некоторые рекомендации о том, как эффективно использовать библиотеки C++ в смешанном режиме, чтобы избежать скачков производительности, которые мы наблюдаем.
-Ник