What problems can arise when using the compiled g ++ file (plugin) in a compiled VC ++ application?

I am using an application compiled using the Visual C ++ compiler. It can load plugins in the form of .dll . It doesn’t matter what it does, fact:

UML Diagram

This includes callers from .dll that return a pointer to an application API object, etc.

My question is: what problems can arise when an application calls a function from .dll , extracts a pointer from it and works with it. For example, something that comes to my mind is the size of the pointer. Difference in VC ++ and g ++? If so, could this lead to the application crashing?

I do not want to use the Visual Studio IDE (which, unfortunately, is the "preferred" way to use the SDK applications). Can I configure g ++ to compile as VC ++?

PS: I am using MINGW GNU g ++

+4
source share
6 answers

As long as both applications and DLLs are compiled on the same computer, and while they both use only C ABI, you should be fine.

What you certainly cannot do is share any C ++ construct. For example, you should not have a new[] array in the main application and let the DLL delete[] it. This is because there is no fixed C ++ ABI, and thus there is no way that any given compiler knows how another compiler implements C ++ data structures. This is also true for different versions of MSVC ++ that are not compatible with ABI.

+6
source

All the features of the C ++ language, I'm afraid, will be completely incompatible. Everything from manipulating names and allocating memory to a virtual call mechanism will be completely different and incompatible. The best you can hope for is a quick, merciful failure.

If your components use only extern "C" interfaces to talk to each other, you can probably do this work, although there, you need to be careful. Both times C ++ will have a startup and shutdown code, and there is no guarantee that whatever linker used to build the application knows how to enable this code for another compiler. For example, you should probably associate g ++ - compiled code with g ++.

If you use C ++ features with only one compiler and use this compiler linker, then it will work with a much greater probability.

+3
source

This should be good if you know what you are doing. But there is something to which you can pay attention:

I assume that the interface between the EXE and the DLL is a β€œC” interface or something like COM, where only public C ++ classes go through clean virtual interfaces. This becomes useless if you export a specific class through a DLL.

  • 32-bit and 64-bit. A 32-bit application will not load a 64-bit DLL and vice versa. Make sure they match.

  • Call agreement. __cdecl vs __stdcall. Often, Visual Studio applications are compiled with flags suggesting that __stdcall is a standard call (or a function prototype explicitly stated). Therefore, make sure that g ++ compilers generate code that matches the calling type expected by the EXE. Otherwise, the exported function may be executed, but the stack may be damaged upon return. If you are debugging such a crash, there is a good chance that the cdecl vs stdcall convention was incorrectly specified. Easy to fix.

  • C-Runtimes are unlikely to be split between EXE and DLL, so do not mix or match. A pointer highlighted by new or malloc in EXE should not be released with deletion or free in a DLL (and vice versa). Likewise, FILE handlers returned by fopen () cannot be split between EXE and DLL. You are likely to crash if any of this happens ... that leads me to the next point ....

  • C ++ header files with embedded code cause a lot of headaches and are the source of the problems that I caused in # 3. You'll be fine if the interface between the DLL and the EXE is a clean "C" interface.

  • Name change problems. If you encounter problems in which the exported function name does not match due to a name change or leading underscore, you can fix this in the .DEF file. At least what I did in the past with Visual Studio. Not sure if equivalent exists in g ++ / MinGW. An example is below. Learn to use "dumpbin.exe / exports" so that you can verify that your DLL is exporting a function with the correct name. Using extern "C" will also help fix this.

      EXPORTS FooBar=_Foobar@12 BlahBlah=??BlahBlah@ @ QAE@XZ @236 NONAME 

These are the problems that I know of. I can’t tell you anymore since you did not explain the interface between the DLL and the EXE.

+3
source

The size of the pointer will not change; which depends on the platform and modularity, and not on the compiler (32-bit and 64-bit, etc.).

What may differ from the size of basically everything else, and what will differ from the templates.

Filling and aligning structures usually depends on the compiler and often depends on the parameters in the compiler. There are such free rules as pointers, usually located on the platform-bit boundary, and bools with 3 bytes after them, but before the compiler, how to handle this.

Templates, especially from STL (which differ for each compiler), can have different elements, sizes, additions and basically anything. The only standard part is the API, the backend remains in the STL implementation (there are some rules, but compilers can still compile the templates). Passing templates between modules from the same assembly is bad enough, but between different compilers it can often be fatal.

Things that are not standardized (name changes) or are especially specific if necessary (memory allocation) will also be incompatible. You can work around both of these problems by destroying only the library that creates (in any case, good practice) and using the STL objects that accept the debit to distribute and export using non-address names and / or C style ( extern "C" ) for exported methods.

It also seems to me that you remember how compilers handle virtual destructors in a vtable with a slight difference.

If you can only make references to your own objects, completely avoid externally visible templates, primarily work with pointers and exported or virtual methods, you can avoid the vast majority of problems (COM does just that, for compatibility with most compilers and languages). It may be a pain to write, but if you need this compatibility, it is possible.

To alleviate some problems, but not all, using an alternative to STL (such as the Qt core library) will fix this particular problem. While throwing Qt into any old project is disgusting waste and will cause more thought than "reinforce ALL THINGS !!!" philosophy, this may be useful for decoupling the library and the compiler to a greater extent than using the STL stock file.

+1
source

The main problems: function signatures and path parameters are passed to the library code. It was very difficult for me to get a VC ++ dll to work in gnu-based compilers. It was back when VC ++ always cost money, and mingw is a free solution.

My experience with the DirectX API. Gradually, the subset received binary files modified by enthusiasts, but they were never so modern and reliable, so after evaluation I switched to the correct cross-platform API, which was SDL.

This wikipedia article describes various ways in which libraries can be compiled and linked. This is more detailed than I can summarize here.

0
source

You cannot pass C runtime objects between them. For example, you cannot open the FILE buffer in one and pass it for use in another. You cannot free allocated memory on the other side.

0
source

Source: https://habr.com/ru/post/1394702/


All Articles