Search code examples
c++visual-c++-6

Error when trying to use functions from dlls


My code:

dll:

#include "stdafx.h"
#include <iostream.h>

extern "C" __declspec(dllexport) void F1()
{
    cout << "It works\n";
}

extern "C" __declspec(dllexport) int F2()
{
    return 154827;
}

extern "C" __declspec(dllexport) void F3(int n)
{
    cout << "It works: "<<n<<"\n";
}

extern "C" __declspec(dllexport) int F4(int n)
{
    return n+1;
}

console application:

#include "stdafx.h"
#include <windows.h>
#include <iostream.h>
#include <stdio.h>
#include <conio.h>

typedef void (WINAPI*f1)();
typedef int (WINAPI*f2)();
typedef void (WINAPI*f3)(int);
typedef int (WINAPI*f4)(int);

#define MAXMODULE 50

f1 F1;
f2 F2;
f3 F3;
f4 F4;

void main(int argc, char* argv[])
{
    HINSTANCE hLib=LoadLibrary("dllll.dll");

    if(hLib==NULL)
    {
        cout << "Unable to load library!" << endl;
        getch();
        return;
   }

    char mod[MAXMODULE];

   GetModuleFileName((HMODULE)hLib, (LPTSTR)mod, MAXMODULE);
   cout << "Library loaded: " << endl;


    F1=(f1)GetProcAddress((HMODULE)hLib, "F1");
    F2=(f2)GetProcAddress((HMODULE)hLib, "F2");
    F3=(f3)GetProcAddress((HMODULE)hLib, "F3");
    F4=(f4)GetProcAddress((HMODULE)hLib, "F4");

   if((F1==NULL) || (F2==NULL) || (F3==NULL) || (F4==NULL)) {

        cout << "Unable to load function(s)." << endl;
        FreeLibrary((HMODULE)hLib);
        return;
   }

   F1();
   cout<<F2()<<endl;
   F3(1515);
   cout << F4(12) << endl;   //works now :)

   FreeLibrary((HMODULE)hLib);

   getch();

    return;
}

Output:

Library loaded:
154827
It works
It works: 1515

Questions:
1. Why is F1 displayed after F2? F1 is called before F2.
2. F3 Works properly but makes a window pop up twice. I click Ignore on it.

(source: ifotos.pl)

  1. Why F4 doesn't work at all? It raises an exception.

EDIT:
Question 2 and 3 are solved now.

For 1, output now is:

Library loaded:  
154827  
13  
It works  
It works: 1515  

Which is in order: F2, F4, F1, F3.
I call them: F1, F2, F3, F4.
Why is it happening?


Solution

  • What's likely happening is that your DLL and your executable are linking against different versions of the C++ runtime library. Since there are now two different versions of the C++ runtime library living in your process's address space, there are two separate memory buffers being used for stdout. Since you're not flushing the data inside your DLL functions but you are flushing it in your executable (note that printing a new line '\n' doesn't flush, but printing a std::endl does flush), this is what happens:

    1. F1 is called, and "It works\n" gets written into your DLL's libc++ stdout memory buffer.
    2. F2 is called, and 154827\n gets written into your executable's libc++ stdout memory buffer. The call to std::endl flushes that buffer and prints it to the console.
    3. F3 is called, and "It works: 1515\n" gets written into your DLL's libc++ stdout memory buffer.
    4. F4 is called, and 13 gets written into your executable's libc++ stdout memory buffer. The call to std::endl flushes that buffer and prints it to the console.
    5. Your process exits, causing your DLL to get unloaded. As part of its cleanup routine, libc++ flushes its output buffers, causing "It works\nIt works: 1515\n" to get printed to the console.

    This fix for this is to make sure that you're using the same C++ (and C) runtime libraries in your DLL and in your executable. See this page for details on that—I recommend using the multithreaded release DLL version (/MD compiler option) for both the executable and DLL.

    See also Potential Errors Passing CRT Objects Across DLL Boundaries.