Как лучше всего избегать двойного преобразования в нативных типах 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?

С уважением

Ник

** ОБНОВИТЬ **

Некоторые обновления из тестирования.

  1. Как только dll скомпилирована с /clr, двойное преобразование происходит для нативных типов (используя dllexport/dllimport).

  2. Этого можно избежать, отключив поддержку CLR для каждого файла отдельно. Это боль, и иногда нативные типы используют clr, так что это нельзя сделать везде. И вызываемый должен быть скомпилирован нативно, чтобы он работал.

  3. Методы могут быть помечены __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++ в смешанном режиме, чтобы избежать скачков производительности, которые мы наблюдаем.

-Ник

0 ответов

Другие вопросы по тегам