0

I'm using Visual Studio 2019 with C++.

I'm trying to load a 32-bit DLL written in C code (not by me) into my C++ application. The dll is something called SDL_mixer.dll (an early version of it, SDL_mixer-1.2.12, which is required). I have to load it via LoadLibrary(), because I don't have the import library. I typedefed the functions to import and used GetProcAddress() to access one of them. It accesses it, but then throws an error when the function is called. It gives a guess at the reason for the problem.

It states:

"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"

I'm not sure what mistake I'm making. I have on occasion called a C DLL from a C++ application using the LoadLibrary method with success.

Here is the code that I have:

typedef int (WINAPI* Mix_OpenAudioA)(int frequency, Uint16 format, int channel, int chunksize);


int main()
{
    const HINSTANCE hLibrary = LoadLibrary(L"SDL_mixer.dll");

    if (hLibrary == NULL) {
        cout << "Unable to open SDL_mixer.dll\n";
        return 0;
    }

    Mix_OpenAudioA mx_OpnAudio = (Mix_OpenAudioA)GetProcAddress(hLibrary, "Mix_OpenAudio");

     // Calling this function is where the error occurs
    if (mx_OpnAudio(44100, AUDIO_S16, 2, 512) < 0) {
        cout << "Audio Initializer Error\n";
        return 0;
    }
}

Thanks for any help! ...John

John Alway
  • 65
  • 10
  • Are you calling a 32 bit dll from a 64 bit program. – Mike Vine Dec 07 '20 at 22:59
  • Verify calling convention [here](https://learn.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-160) – lsalamon Dec 07 '20 at 23:03
  • 2
    I see no hint in the SDL source code that you should use WINAPI (aka `__stdcall`). Nor is it the kind of library that would favor it. So delete it and try again. – Hans Passant Dec 07 '20 at 23:07
  • @Mike Vine -- No, it's a 32-bit application. – John Alway Dec 07 '20 at 23:18
  • @Hans Passant -- Thank you! That was it. I have a lot to learn about these calling conventions. – John Alway Dec 07 '20 at 23:20
  • Is there a way to give someone credit for an answer on here? Like some kind of a thumbs up? – John Alway Dec 07 '20 at 23:22
  • @JohnAlway "*I have to load it via LoadLibrary(), because I don't have the import library*" - most compile toolchains that support DLLs will provide a tool to generate an import lib from a DLL file. – Remy Lebeau Dec 07 '20 at 23:50
  • @JohnAlway "*Is there a way to give someone credit for an answer on here? Like some kind of a thumbs up?*" - had the person posted an actual answer, you could upvote it and mark it as accepted. But as the solution was posted in a comment, all you can do is upvote the comment. – Remy Lebeau Dec 07 '20 at 23:52
  • @JohnAlway the reason removing `WINAPI` works is because the DLL functions were likely compiled with the `__cdecl` calling convention, which is commonly the default calling convention used by many compilers when no calling convention is specified. So, in this case, when removing `WINAPI` your compiler then happens to default to the same convention that the DLL is using. When interfacing with external libraries, is is not a bad idea to be more explicit about the calling convention used, eg: `typedef int (__cdecl * Mix_OpenAudioA)(int frequency, Uint16 format, int channel, int chunksize);` – Remy Lebeau Dec 07 '20 at 23:55

0 Answers0