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中的导出函数里可能是叫做Add1@SANNN@之类之类的,不方便动态调用(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;