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)
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?
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:
"It works\n"
gets written into your DLL's libc++ stdout memory buffer.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."It works: 1515\n"
gets written into your DLL's libc++ stdout memory buffer.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."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.