我的代码:
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;
}
控制台应用程序:
#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;
}
输出:
Library loaded:
154827
It works
It works: 1515
问题:
1.为什么在F2之后显示F1?在F2之前调用F1
2. F3正常工作,但会弹出两次窗口。我点击忽略它。
http://s3.ifotos.pl/img/f3_hwpwapq.jpg
3.为什么F4根本不起作用?它提出了一个例外。
编辑:
问题2和3现在已经解决了。
对于1,现在输出为:
Library loaded:
154827
13
It works
It works: 1515
按顺序:F2,F4,F1,F3。
我称之为:F1,F2,F3,F4
为什么会这样?
答案 0 :(得分:2)
看起来你有错误的调用约定。尝试将WINAPI
(__stdcall
)更改为__cdecl
。
typedef void (__cdecl *f1)();
typedef int (__cdecl *f2)();
typedef void (__cdecl *f3)(int);
typedef int (__cdecl *f4)(int);
答案 1 :(得分:2)
可能发生的事情是您的DLL和可执行文件链接到不同版本的C ++运行时库。由于现在有两个不同版本的C ++运行时库存在于进程的地址空间中,因此有两个独立的内存缓冲区用于stdout。由于您没有刷新DLL函数中的数据,但是 在可执行文件中刷新它(请注意,打印新行'\n'
不会刷新,而是打印{{1 做 flush),这就是:
std::endl
被写入DLL的libc ++ stdout内存缓冲区。"It works\n"
写入可执行文件的libc ++ stdout内存缓冲区。对154827\n
的调用会刷新缓冲区并将其打印到控制台。std::endl
写入DLL的libc ++ stdout内存缓冲区。"It works: 1515\n"
写入可执行文件的libc ++ stdout内存缓冲区。对13
的调用会刷新缓冲区并将其打印到控制台。std::endl
打印到控制台。此修复程序是为了确保您在DLL和可执行文件中使用相同的C ++(和C)运行时库。有关详细信息,请参阅this page - 我建议对可执行文件和DLL使用多线程版本DLL版本("It works\nIt works: 1515\n"
编译器选项)。
另见Potential Errors Passing CRT Objects Across DLL Boundaries。