This question is about using C-Functions from a MinGW dll in a VC++ project, which fails with the following error: Run-Time Check Failure #0.
I successfully build clang and more importantly libclang using MinGW (to have a libclang.dll that uses the MinGW standard library).
My application previously used a VC++-build of libclang, that I now want to exchange with the MinGW build.
To do that, I created a def-file and afterwards an import library from the MinGW dll file:
dlltool -z libclang.def --export-all-symbol libclang.dll
dlltool -d libclang.def -l libclang.lib
Before creating the import library, I altered the def-file so it only contains the important clang-functions that have been declared using extern "C". Here is a small excerpt:
LIBRARY libclang.dll
EXPORTS
clang_CXCursorSet_contains @ 50006
clang_CXCursorSet_insert @ 50007
clang_CXXMethod_isStatic @ 50008
clang_CXXMethod_isVirtual @ 50009
clang_Cursor_getTranslationUnit @ 50010
Using the MinGW dll and the new import library, I can now successfully compile my application. It runs and I can actually use some functions like "clang_createIndex", but whenever I get to "clang_getTranslationUnitCursor" I get a:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
The functions inside Clang's Index.h (and thus out of my control) are declared like this:
#ifdef _MSC_VER
#ifdef _CINDEX_LIB_
#define CINDEX_LINKAGE __declspec(dllexport)
#else
#define CINDEX_LINKAGE __declspec(dllimport)
#endif
#else
#define CINDEX_LINKAGE
#endif
CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
I have actually no idea, why it works for some functions and not for others!
Thanks a lot!
[Update]
For lovers of assembly, here is some example assembly that leads to the crash. The call to clang_getNumDiagnostics works, the call to clang_getTranslationUnitCursor fails in the last line, when calling __RTC_CheckEsp - which is the function that checks the correctness of ESP
// call to clang_getNumDiagnostics(TU); - works!
5AF3EFAB mov esi,esp
5AF3EFAD mov eax,dword ptr [ebp-30h]
5AF3EFB0 push eax
5AF3EFB1 call dword ptr [__imp__clang_getNumDiagnostics (5AF977E0h)]
5AF3EFB7 add esp,4
5AF3EFBA cmp esi,esp
5AF3EFBC call @ILT+7135(__RTC_CheckEsp) (5AF16BE4h)
// call to clang_getTranslationUnitCursor(TU); - fails!
5AF3EFC1 mov esi,esp
5AF3EFC3 mov eax,dword ptr [ebp-30h]
5AF3EFC6 push eax
5AF3EFC7 lea ecx,[ebp-234h]
5AF3EFCD push ecx
5AF3EFCE call dword ptr [__imp__clang_getTranslationUnitCursor (5AF9780Ch)]
5AF3EFD4 add esp,8
5AF3EFD7 cmp esi,esp
5AF3EFD9 call @ILT+7135(__RTC_CheckEsp) (5AF16BE4h)
During the call of clang_getTranslationUnitCursor the esp will be increased by 4. The big question is, for both function calls which take the same parameter, why is it "add esp,4" after the the call to clang_getNumDiagnostics, but "add esp,8" when calling clang_getTranslationUnitCursor??