由于自己对DLL不是很熟,准备转载几篇别人的DLL系列文章。
四种dll:
none_mfc dll;
mfc dll with static link mfc
mfc dll shared mfc
extend mfx dll
///
dll 在编译后会生成dll 和lib文件。 如果我们是显示地使用dll的话则只要用dll文件就可以了。。
如果要隐士的使用dll文件则需要 dll , lib .还有头文件。
//。。。。。。。。。
//dll 部分。
// trydll2.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "trydll2.h"
//..............................
#include <iostream>
using namespace std;
///...............................
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
TRYDLL2_API int nTrydll2=0;
// This is an example of an exported function.
TRYDLL2_API int fnTrydll2(void)
{
cout<<"fnTrydll2 \n";
return 42;
}
// This is the constructor of a class that has been exported.
// see trydll2.h for the class definition
CTrydll2::CTrydll2()
{
return;
}
//。。trydll2.h。。。。。。。。。。。。。。。。。。
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TRYDLL2_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TRYDLL2_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef TRYDLL2_EXPORTS
#define TRYDLL2_API __declspec(dllexport)
#else
#define TRYDLL2_API __declspec(dllimport)
#endif
// This class is exported from the trydll2.dll
class TRYDLL2_API CTrydll2 {
public:
CTrydll2(void);
// TODO: add your methods here.
};
extern TRYDLL2_API int nTrydll2;
/*
extern "C"
{
TRYDLL2_API int fnTrydll2(void);
};
*/
TRYDLL2_API int fnTrydll2(void);//在c++文件中使用会出错
//c++编译器对函数进行改名 修改后的名字依赖于 未修改的函数名,函数的参数类型,函数的参数个数
//函数所在的类(如果有),函数所在的文件。
//我在用隐士方法利用dll时,由于dll中的函数(设为void fn() )没有声明为extern "C",所以按照c++规则修改
//然后再客户端(dll为服务器)直接用函数fn(),编译能够进行但是在运行时出错,
//系统提示:无法找到函数的入口点。因为客户端的fn也进行了改名,结果修改后的名字和服务器修改后的名字不一样
//所以 我才猜测 c++对函数名的修改也依赖于文件名..
//事实我的猜测是错误的,但是记住,不要把希望寄托在 系统改名会让连个函数名字一样
//。。。。。。。。。。
上面的东西便以后生成 trydll2.dll,trydll2.lib
//..................................................
//显式利用dll
#include "stdafx.h"
//#include "trydll2.h"
#include "windows.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
HINSTANCE hi=::LoadLibrary("E:\\lianxi\\DLL_LIB_DCOM_COM\\trydll2\\Debug\\trydll2.dll");
if( hi == NULL )
{
cout<<"LoadLibrary error\n";
return 0;
}
//fnTrydll2:别忘了C++默认编译器会对函数进行改名
//所以你应该强制什么声明不应该改名
//但是这样的话 重载就有麻烦了。。因为重载就是应用了改名的方法
FARPROC lpfn= ::GetProcAddress( hi , "fnTrydll2" );
if( lpfn == NULL )
{
cout<<"GetProcAddress error\n";
return 0;
}
lpfn();
//fnTrydll2();
/*
怎么使用导出的类或者变量呢??
*/
::FreeLibrary( hi );
return 0;
}
//所谓的显示 就是因为你是用了 loadlibrary getproaddress,freelibrary
//.隐士利用dll
#include "stdafx.h"
/*
隐士调用的方法:假如头文件 eg:#include "..\trydll2.h"
假如生成dll时生成的lib文件。
直接调用函数。eg:fnTrydll2();
*/
#include "..\trydll2.h" //必须
#include "windows.h"
#include <iostream>
using namespace std;
//此外还有在 工程的连接库里加入 trydll2.lib
int main(int argc, char* argv[])
{
cout<<"used dll with hide way:";
//fnTrydll2:别忘了C++默认编译器会对函数进行改名
//所以你应该强制什么声明不应该改名
//但是这样的话 重载就有麻烦了。。因为重载就是应用了改名的方法
fnTrydll2();
/*
怎么使用导出的类或者变量呢??
*/
// ::FreeLibrary( hi );
return 0;
}
如果采用隐士的话 每一次dll修改,则需要重新编译客户端。此外 这种方法在程序启动时就会夹在所有需要的dll