Dll compatibility between compilers

后端 未结 9 1681
小蘑菇
小蘑菇 2021-01-02 08:35

Is there some way to make c++ dlls built with diffrent compilers compatible with each other? The classes can have factory methods for creation and destruction, so each compi

相关标签:
9条回答
  • 2021-01-02 08:51

    One way you might be able to organize the code is to use classes in both the app and the dll, but keep the interface between the two as extern "C" functions. This is the way I have done it with C++ dlls used by C# assemblies. The exported DLL functions are used to manipulate instances accessible via static class* Instance() methods like this:

    __declspec(dllexport) void PrintSomething()
    {
        (A::Instance())->PrintSometing();
    }
    

    For multiple instances of objects, have a dll function create the instance and return the identifier, which can then be passed to the Instance() method to use the specific object needed. If you need inheritance between the app and the dll, create a class on the app side that wraps the exported dll functions and derive your other classes from that. Organizing your code like this will keep the DLL interface simple and portable between both compilers and languages.

    0 讨论(0)
  • 2021-01-02 08:52

    interesting.. what happens if you compile the dll in VC++ as well, and what if you put some debug statements in CreateClass()?

    I'd say its possible that your 2 different runtime 'versions' of cout are conflicting instead of your method call - but I trust that the returned function pointer/dllclass isn't 0x00000004?

    0 讨论(0)
  • 2021-01-02 08:54

    You're almost certainly asking for trouble if you do this - while other commenters are correct that the C++ ABI may be the same in some instances, the two libraries are using different CRTs, different versions of the STL, different exception throwing semantics, different optimizations... you're heading down a path towards madness.

    0 讨论(0)
  • 2021-01-02 08:57

    I think you'll find this MSDN article useful

    Anyway, from a quick glance at your code, I can tell you that you should not declare a virtual destructor in an interface. Instead, you need to do delete this within A::Release() when the ref count drops to zero.

    0 讨论(0)
  • 2021-01-02 09:02

    You do critically depend on the v-table layout being compatible between VC and GCC. That is somewhat likely to be okay. Ensuring that the calling convention matches is something you should check (COM: __stdcall, you: __thiscall).

    Significantly, you are getting a AV on writing. Nothing is being written when you make the method call itself, so it is likely that operator<< is doing the bombing. Does std::cout get probably initialized by the GCC runtime when a DLL is loaded with LoadLibrary()? The debugger should tell.

    0 讨论(0)
  • 2021-01-02 09:06

    You should be able to mix modules built with different compilers if you lower your expectations and stick to simple functions.

    The way classes and virtual functions behave is defined by the C++ standard, but the way that's implemented is up to the compiler. In this case, I know that VC++ builds objects which have virtual functions with a "vtable" pointer in the first 4 bytes of the object (I'm assuming 32-bit), and that points to a table of pointers to the method entry points.

    So the line: dllclass->PrintSomething(); is actually equivalent to something like:

    struct IClassVTable {
        void (*pfIClassDTOR)           (Class IClass * this) 
        void (*pfIRefCountedAddRef)    (Class IRefCounted * this);
        void (*pfIRefCountedRelease)   (Class IRefCounted * this);
        void (*pfIClassPrintSomething) (Class IClass * this);
        ...
    };
    struct IClass {
        IClassVTable * pVTab;
    };
    (((struct IClass *) dllclass)->pVTab->pfIClassPrintSomething) (dllclass);
    

    If the g++ compiler is implementing the virtual function tables in any way differently from MSFT VC++ -- as it is free to do and still be conformant to the C++ standard -- this will just crash as you've demonstrated. The VC++ code expects the function pointers to be in particular places in memory (relative to the object pointer).

    It gets more complicated by inheritance, and really, really, complicated with multiple inheritance and virtual inheritance.

    Microsoft has been very public about the way VC++ implements classes, so you can write code that depends on it. For example, a lot of COM object headers distributed by MSFT have both C and C++ bindings in the header. The C bindings expose their vtable structure like my code above does.

    On the other hand, GNU -- IIRC -- has left open the option of using different implementations in different releases, and just guaranteeing the programs built with it's compiler (only!) will conform to the standard behaviour,

    The short answer is to stick to simple C-style functions, POD structures (Plain Old Data; i.e., no virtual functions), and pointers to opaque objects.

    0 讨论(0)
提交回复
热议问题