传统上,我一直在使用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库导入本机类型?
此致
尼克
**更新**
测试的一些更新。
只要使用/ clr编译dll,就会对本机类型进行双重thunking(使用dllexport / dllimport)。
可以通过逐个文件地关闭CLR支持来减轻这种情况。这是一种痛苦,有时本机类型使用clr,因此无法在任何地方进行此操作。并且被调用者也必须编译为原生才能使其正常工作。
可以将方法标记为__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);
};
这个编译,我现在可以从库外部使用调用者类,它不会导致双重thunk。这就是我想要的。但是,我担心这不是这样做的方法;我没有看到任何暗示这种方法是安全的东西。
我真的很喜欢有关如何有效使用混合模式C ++库的一些指导原则,以避免我们所看到的性能影响。
-Nick