How to best avoid double thunking in C++/CLI native types

本秂侑毒 提交于 2019-12-24 00:18:59

问题


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.

  1. As soon as the dll is compiled with /clr, double thunking occurs for native types (using dllexport/dllimport).

  2. 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.

  3. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!