DLL入门 -- 转载

上一篇 / 下一篇  2008-11-18 13:36:34 / 个人分类:DLL相关

  由于自己对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


TAG: DLL相关

 

评分:0

我来说两句

Open Toolbar