VS中 DLL的创建及函数导出(参考MSDN)

新建一个DLL工程

  新建 - 项目 - vc++ - win32 - win32控制台应用程序,工程名假设取为 MathFuncsDll

  

向导中选择DLL,取消预编译头

完成。

此时会有dllmain.cpp, MathFuncsDll.cpp 两个cpp文件及生成的 stdafx.h, targetver.h stdafx.cpp, 后面这三个文件其实是没用的,可以删掉,然后把dllmain.cpp 中的#include "stdafx.h"改成#include <windows.h>

给工程添加一个头文件MathFuncsDll.h用来定义我们的函数,现在的工程文件如图:

在DLL中函数导出有两种方式,一种是利用__declspec(dllexport)语句声明函数,这样便不需要def文件即可导出函数,比如

extern "C" __declspec(dllexport) double  Add1(double a, double b);

对应的函数定义

__declspec(dllexport) double Add1(double a, double b) {
        return a + b;
    }

这里extern "C" 是为了在DLL中生成的函数名不会变化,如果不用该句,Add1在DLL中的导出函数里可能是叫做[email protected]@之类之类的,不方便动态调用(LoadLibrary,GetProcAddress)。

通过denpency walker可以看DLL的导出函数及其名称,这里显示的名称就是GetProcAddress()函数需要的名称,如果名称不对将获取不了函数

  

另一种方法是利用def文件,这种方法得到的导出函数名称更好看,适合动态调用。此时函数的定义就可以写的比较简单了

double Divide2(double a, double b);

double Divide2(double a, double b) {
    if (b == 0)
        throw invalid_argument("b cannot be zero!");
    return a / b;
}

在工程中插入def文件,按下面代码编写

LIBRARY    MathFuncsDll
EXPORTS
    Divide2 @1

第一行是LIBRARY关键字,后接库名称

第二行是EXPORTS关键字

再往下就是要导出的函数名及其序号。

附上代码:

// MathFuncsDll.cpp : 定义 DLL 应用程序的导出函数。
//

#include "MathFuncsDll.h"
#include <stdexcept>

using namespace std;

namespace MathFuncs {
    double MyMathFuncs::Add(double a, double b) {
        return a + b;
    }

    double MyMathFuncs::Subtract(double a, double b) {
        return a - b;
    }

    double MyMathFuncs::Multiply(double a, double b) {
        return a * b;
    }

    double MyMathFuncs::Divide(double a, double b) {
        if (b == 0)
            throw invalid_argument("b cannot be zero!");
        return a / b;
    }
}
MATHFUNCSDLL_API double Add1(double a, double b) {
        return a + b;
    }

MATHFUNCSDLL_API double Subtract1(double a, double b) {
        return a - b;
    }

MATHFUNCSDLL_API double Multiply1(double a, double b) {
        return a * b;
    }

MATHFUNCSDLL_API double Divide1(double a, double b) {
        if (b == 0)
            throw invalid_argument("b cannot be zero!");
        return a / b;
}

double Divide2(double a, double b) {
    if (b == 0)
        throw invalid_argument("b cannot be zero!");
    return a / b;
}

头文件:

#pragma once

#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif

namespace MathFuncs {
    class MyMathFuncs {
    public:
        static MATHFUNCSDLL_API double Add(double a, double b);
        static MATHFUNCSDLL_API double Subtract(double a, double b);
        static MATHFUNCSDLL_API double Multiply(double a, double b);
        static MATHFUNCSDLL_API double Divide(double a, double b);

    };
}
extern "C" MATHFUNCSDLL_API double  Add1(double a, double b);
extern "C" MATHFUNCSDLL_API double Subtract1(double a, double b);
extern "C" MATHFUNCSDLL_API double Multiply1(double a, double b);
extern "C" MATHFUNCSDLL_API double Divide1(double a, double b);
double Divide2(double a, double b);

这里除了普通的函数,还有在命名空间中的类的静态函数。不过这种函数通过GetProcAddress()将会很难调用,如果是通过链接lib文件来调用则会比较容易,比如

cout << "a + b = " <<
        MathFuncs::MyMathFuncs::Add(a, b) << endl;
时间: 2024-08-06 11:51:01

VS中 DLL的创建及函数导出(参考MSDN)的相关文章

Delphi中DLL的创建和使用【转】

Delphi中DLL的创建和使用     1.DLL简介:   2.调用DLL:   3.创建DLL:   4.两个技巧:   5.初始化:   6.例外处理.            1.DLL简介     DLL是Dynamic-Link   Libraries(动态链接库)的缩写,库里面是一些可执行的模块以及资源(如位图.图标等).可以认为DLL和EXE基本上是一回事,只是DLL不能直接执行,而必须由应用程序或者其他DLL调用.DLL为应用程序间的资源共享提供了方便,同时也是多语言混合编程的

C++中对Mysql的操作函数可以参考以下blog中的内容

http://www.cnblogs.com/lovebread/archive/2009/11/24/1609936.html

编写DLL所学所思(1)——导出函数

烛秋  http://www.cnblogs.com/cswuyg/archive/2011/09/30/dll.html 动态链接库的使用有两种方式,一种是显式调用.一种是隐式调用. (1)       显式调用:使用LoadLibrary载入动态链接库.使用GetProcAddress获取某函数地址. (2)       隐式调用:可以使用#pragma comment(lib, “XX.lib”)的方式,也可以直接将XX.lib加入到工程中. DLL的编写 编写dll时,有个重要的问题需要

包——基本概念,自定义包,创建包,导出包中的标志符

1.基本概念 Go语言是使用包来组织源代码的,并实现命名空间的管理.任何源代码文件必须属于某个包.源码文件的第一行有效代码必须是 package pacakgeName 语句,通过该语句声明自己所在的包. 1)概念 Go语言的包借助了目录树的组织形式,一般包的名称就是其源文件所在目录的名称,虽然 Go 没有强制包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰. 包可以定义在很深的目录中,包的定义是不包括目录路径的,但是包的引用一般是全路径引用.比如在 $GOPATH/s

dbus 创建Client过程中几个有用的函数

/**  * g_type_init:  *  * This function used to initialise the type system.  Since GLib 2.36,  * the type system is initialised automatically and this function does  * nothing.  *  * Deprecated: 2.36: the type system is now initialised automatically

分析ntdll.dll和ntoskrnl.exe中的 NT*和ZW*函数区别

OpenProcess-->ntdll!NtOpenProcess-->ntdll!zwOpenProcess-->ntdll!KiFastSystemCall() ↓mov edx, esp ↓sysenter 用户层------------------------------------------------------------------------------------------------------ ↓ 内核层 nt!KiFastCallEntry()      

VC++中.DLL文件与.LIB文件关系

一般的LIB文件是"导入库",用来提供给link.exe,作为链接DLL--也就是"动态链接库"的依据.里面记录了类似下面的信息:调用函数xxx(),连接到x.dll的0xABCDEFGH地址:-- 早期的LIB,是"静态链接库",也是用来提供给link.exe,作为链接代码用的.里面的记录如下:调用xxx(),其代码是--:DLL的LIB(导入库),不含可执行的具体代码(代码在DLL中).而最早的LIB(静态链接库),里面含有代码.所以,可以看

Delphi中DLL的其他应用

http://blog.csdn.net/zhenghui1/article/details/6618273 1.DLL的入口函数和出口函数 在编写DLL时可以在DLL项目文件的begin..end之间加入DLL的进入口函数和出口函数,全局变量DLLProc是一个过程指针,指定入口/出口函数,初始值为nil,只需将自己的出入口函数赋值给它即可,自己的出入口函数必须传入一个DWord类型的参数.一下是出入口函数事件对应的用途. DLL_PROCESS_ATTACH 在进程启动或调用LoadLibr

C#中dll调用方法

一.      DLL与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library”的缩写)是Microsoft Windows最重要的组成要素之一,打开Windows系统文件夹,你会发现文件夹中有很多DLL文件,Windows就是将一些主要的系统功能以DLL模块的形式实现. 动态链接库是不能直接执行的,也不能接收消息,它只是一个独立的文件,其中包含能被程序或其它DLL调用来完成一定操作的函数(方法.注:C#中一般称为“方法”),但这些函数不是执行程序本身的一部分,而是根