四种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=:oadLibrary("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 |