DLL的编写与调用,简单示例

1.新建一个DLL类型的应用程序,如:myDll.cpp

extern "C"

    在 DLL的设计中中,,如果使用C++开发,通常在导出函数的定义中使用extern "C",为什么呢?因为当用户使用"运行时动态链接"的时候将使用GetProcAddress函数得到导出函数的地址,该函数是通过导出函数的函数名定位导出函数的,而C++编译器因为函数重载的原因会对开发者定义的函数名进行修饰,导致导出表中的函数名通常不是开发者使用的函数名,比如函数 ExportedFn可能被修饰成??ExportedFn@QAEX 。所以使用extern "C"通知编译器按照C的格式进行编译,而不是使用C++的方法进行编译。使用VS提供的一个工具Dependency Walker可以查看DLL的导出函数。

_declspec

    http://support.microsoft.com/kb/132044

 

2.新建一个win32控制台应用程序,如:TestDll.cpp

typedef int (*FUNC)(int , int)

    函数指针,用以指向DLL中的函数, 返回值、参数个数要与其匹配

LoadLibrary(...)

    载入指定的动态链接库,并将它映射到当前进程使用的地址空间。一旦载入,即可访问库内保存的资源。

GetProcAddress(...)

    检索指定的动态链接库(DLL)中的输出库函数地址。

FreeLibrary(...)

    释放指定的动态链接库,它们早先是用LoadLibrary API函数装载的。

 3.上面是DLL的显示调用,看起来比较麻烦但是它只要一个dll文件就可以了;
下面是DLL的隐式调用, 用起来比较简单但是它需要三个文件:.h, .lib, .dll。
新建一个dll工程,注意工程属性->Preprocessor里面会有个_USRDLL宏
如下代码:

// dlltest.h
#ifndef _DLL_TEST_H_
#define _DLL_TEST_H_

#ifdef _USRDLL
 #define DLLTEST_API __declspec(dllexport)
#else
 #define DLLTEST_API __declspec(dllimport)
#endif

DLLTEST_API int Sum(int x, int y);

class DLLTEST_API Coord
{
public:
	Coord(int x, int y);
	void Print();

private:
	int x_, y_;
};

#endif // _DLL_TEST_H_

// dlltest.cpp
#include "dlltest.h"
#include <iostream>

int Sum(int x, int y)
{
	return x+y;
}

Coord::Coord(int x, int y)
 : x_(x), y_(y)
{
}

void Coord::Print()
{
	std::cout << "x = " << x_ << ", y = " << y_ << std::endl;
}

编译会生成dlltest.lib和dlltest.dll

测试DLL
首先,在用的时候包含dlltest.h头文件,测试程序C/C++->Additional Include Directories里面指定dlltest.h目录;
其次,Linker->Additional Library Directories里面指定dlltest.lib目录,以及
 Linker->Input->Additional Dependencies里面填写dlltest.lib,这样就可以通过编译;

最后,要运行还需要dlltest.dll文件,将其文件放在与测试程序exe同一目录下即可(当然系统目录下也可以只要exe运行时可以找到)。


这是apr里面的一个例子:

// 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 SAMPLEDLL_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 
// SAMPLEDLL_API functions as being imported from a DLL, wheras this DLL sees symbols
// defined with this macro as being exported.
#ifdef SAMPLEDLL_EXPORTS
#define SAMPLEDLL_API __declspec(dllexport)
#else
#define SAMPLEDLL_API __declspec(dllimport)
#endif

// This class is exported from the SampleDLL.dll
class SAMPLEDLL_API CSampleDLL {
public:
	CSampleDLL(void);
	// TODO: add your methods here.
};

extern SAMPLEDLL_API int nSampleDLL;

SAMPLEDLL_API int fnSampleDLL(void);

// SampleDLL.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include "SampleDLL.h"

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
SAMPLEDLL_API int nSampleDLL=0;

// This is an example of an exported function.
SAMPLEDLL_API int fnSampleDLL(void)
{
	return 42;
}

// This is the constructor of a class that has been exported.
// see SampleDLL.h for the class definition
CSampleDLL::CSampleDLL()
{ 
	return; 
}


2011-03-06

23:57:46

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值