问题
Tradionally, I've been using MFC extension dll's and importing/exporting using dllimport/dllexport.
However, when the dll is changed to use /clr, this method becomes costly as calls can result in a double-thunk. I'm taking a massive performance hit at the moment and need to stop the double-thunks. The solution I've seen described suggests making sure everything is using __clrcall convention, but this does not work with dllexport.
Microsoft's own section on double-thunking suggests:
Similarly, if you export (dllexport, dllimport) a managed function, a native entry point is generated and any function that imports and calls that function will call through the native entry point. To avoid double thunking in this situation, do not use native export/import semantics; simply reference the metadata via #using (see #using Directive (C++)).
To me, this reads as though I can remove dllexport/dllimport from my classes and stick a #using in my stdafx.h. For native types, however, this results in LNK2028 (unresolved token) and LNK2019 (unresolved external symbol). It makes no difference whether I include the .lib in the linker or not; I still get this error.
So, my question is how best to avoid double-thunking and import native types from a C++/CLI library?
Regards
Nick
** UPDATE **
Some updates from testing.
As soon as the dll is compiled with /clr, double thunking occurs for native types (using dllexport/dllimport).
This can be mitigated by turning CLR support off on a file by file basis. This is a pain, and sometimes native types use the clr so this can't be done everywhere. And the callee must be compiled native too for it to work.
Methods can be marked __clrcall but this will result in a compilation error when mixed with dllexport. However, I have managed to make the following code work without a double-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); };
This compiles and I can use the caller class now from outside the library and it doesn't result in a double thunk. Which is what I want. I'm concerned, however, that this is not the way to do it; I haven't read anything that suggests this approach is safe.
I'd really like some guidelines on how to used mixed-mode C++ libraries effeciently to avoid performance hits of the like we are seeing.
-Nick
来源:https://stackoverflow.com/questions/18964076/how-to-best-avoid-double-thunking-in-c-cli-native-types