如何最好地避免C ++ / CLI本机类型中的双重thunking

时间:2013-09-23 16:15:01

标签: mfc c++-cli

传统上,我一直在使用MFC扩展dll并使用dllimport / dllexport导入/导出。

但是,当dll更改为使用/ clr时,此方法变得昂贵,因为调用可能导致双重thunk。我现在正在大力打击,需要停止双击。我见过的解决方案建议确保所有内容都使用__clrcall约定,但这不适用于dllexport。

微软自己关于双重线索的部分建议:

  

同样,如果导出(dllexport,dllimport)托管函数,则会生成本机入口点,并且导入和调用该函数的任何函数都将通过本机入口点进行调用。为避免在这种情况下双重thunking,请不要使用本机导出/导入语义;只需通过#using引用元数据(参见#using Directive(C ++))。

对我而言,这就好像我可以从我的类中删除dllexport / dllimport并在我的stdafx.h中添加#using。但是,对于本机类型,这会导致LNK2028(未解析的令牌)和LNK2019(未解析的外部符号)。我是否在链接器中包含.lib没有区别;我仍然得到这个错误。

所以,我的问题是如何最好地避免双重thunking并从C ++ / CLI库导入本机类型?

此致

尼克

**更新**

测试的一些更新。

  1. 只要使用/ clr编译dll,就会对本机类型进行双重thunking(使用dllexport / dllimport)。

  2. 可以通过逐个文件地关闭CLR支持来减轻这种情况。这是一种痛苦,有时本机类型使用clr,因此无法在任何地方进行此操作。并且被调用者也必须编译为原生才能使其正常工作。

  3. 可以将方法标记为__clrcall,但这与dllexport混合时会导致编译错误。但是,我设法使以下代码在没有双重thunk的情况下工作:

    // 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);
    };
    
  4. 这个编译,我现在可以从库外部使用调用者类,它不会导致双重thunk。这就是我想要的。但是,我担心这不是这样做的方法;我没有看到任何暗示这种方法是安全的东西。

    我真的很喜欢有关如何有效使用混合模式C ++库的一些指导原则,以避免我们所看到的性能影响。

    -Nick

0 个答案:

没有答案