VS创建与使用DLL文件(提示找不到Dll函数解决办法)

时间:2024-03-01 16:13:51

1、创建DLL文件

(1) 创建一个工程CreateDll

 

(2) 刚创建的项目结构

(3) Header Files下添加一个头文件myDll.h

 

 

 文件内容

//myDll.h
#ifdef MYDLL_EXPORTS  
#define MYDLL_API __declspec(dllexport)   
#else  
#define MYDLL_API __declspec(dllimport)   
#endif 

namespace MyNameSpace{
    class MyClass
    {
    public:
        static MYDLL_API void printHello();
        static MYDLL_API double add(double number1, double number2);
        static MYDLL_API char* returnString();
    };
}

(4) 在Source Files添加一个cpp文件myDll.cpp

 

文件内容

//myDLL.cpp
#include"stdafx.h"
#include"myDll.h"
#include<iostream>
#include<stdio.h>

using namespace std;

namespace MyNameSpace{
    double MyNameSpace::MyClass::add(double number1, double number2){
        return number1 + number2;

    }
    void MyNameSpace::MyClass::printHello(){
        std::cout << "Hello World" << std::endl;

    }
    char* MyNameSpace::MyClass::returnString(){
        char* returnStr = "This is my string for return";
        return returnStr;
    }
}

(5) 添加完头文件和cpp文件后项目结构

(6) 点击编译或Ctrl+Shift+B

(7) 生成的Dll文件和Lib文件在Debug目录下

2、查看生成的CreateDll.dll提供的接口

(1) 查看命令

dumpbin.exe /EXPORTS D:\AAA_CODE\Test_Code\CallDll\Debug\CreateDll.dll

(2) dumpbin.exe路径

存放在VS2013安装目录下VC下的Bin里,例如:D:\VS2013\VC\bin\dumpbin.exe

(3) 运行命令,查看接口名称

(4) 接口名说明

由图可知,接口名称已经不是add,printHelloreturnString了。这是由于采用了C++的编译方式,导致接口被重命名了。

2、使用DLL文件

(1) 静态调用

① 创建一个工程CallDll

 

 

② 添加myDll.h头文件目录 (添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。)

 

 

 

③ 添加CreateDll.lib目录(添加文件引用的lib静态库路径: 工程---属性---配置属性---链接器---常规---附加库目录:加上lib文件存放目录。)

 

 

④ 添加CreateDll.liblib名称( 添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入---附加依赖项:加上lib文件名。)

 

 

⑤ 添加一个staticCall.cpp用于写调用代码

#include <iostream>  
#include "myDll.h"
using namespace std;

int main()
{
    double a = 10.0;
    int b = 5.0;
    cout << "5.0 + 10.0 = " << MyNameSpace::MyClass::add(5.0, 1.0) << endl; //命名空间::类名::函数名
    MyNameSpace::MyClass::printHello();
    cout << "ret:" << MyNameSpace::MyClass::returnString() << endl;
    cin.get();
    return 0;
}

 ⑥ 添加DLL文件到Debug目录(没找到Debug目录时,可以先运行一下程序,就会自动生成)

⑦ 工程结构

 

⑧ 运行程序,查看结果。

 

(2) 动态调用

① 新建工程与静态调用一样。(这次直接用的同一个工程)

② 添加dynamicCall.cpp

//dynamicCall.cpp

#include<iostream>

#include<Windows.h>

using namespace std;

 

void addMode(){

typedef double(*add)(double number1, double number2);

char* dllName = "CreateDll.dll";

HMODULE dllHandler = LoadLibrary(dllName);

if (dllHandler != NULL){

//直接使用第一个函数(第二个,第三个同理)

add testAdd = add(GetProcAddress(dllHandler, MAKEINTRESOURCE(1)));

if (testAdd != NULL){

cout << "5.0 + 6.3 = " << testAdd(5.0, 6.3) << endl;

}

else{

cout << "Can not find function add" << endl;

}

}

else

{

cout << "Load Library fail:" << dllName << endl;

}

}

 

void printHelloMode(){

typedef void(*printHello)();

char* dllName = "CreateDll.dll";

HMODULE dllHandler = LoadLibrary(dllName);

if (dllHandler != NULL){

//通过映射函数名来使用PrintHello函数(其他两个函数同理)

printHello testPrintHello = printHello(GetProcAddress(dllHandler, "?printHello@MyClass@MyNameSpace@@SAXXZ"));

if (testPrintHello != NULL){

testPrintHello();

}

else{

cout << "Can not find function printHello" << endl;

}

}

else

{

cout << "Load Library fail:" << dllName << endl;

}

}

 

void returnStrMode(){

typedef char(*returnStr)();

char* dllName = "CreateDll.dll";

HMODULE dllHandler = LoadLibrary(dllName);

if (dllHandler != NULL){

//两种方法实现returnStr

returnStr testReturnStr = returnStr(GetProcAddress(dllHandler, "?returnString@MyClass@MyNameSpace@@SAPADXZ"));

if (testReturnStr != NULL){

cout << "Mode by get function name:" << testReturnStr() << endl;

}

else{

cout << "Can not find function printHello" << endl;

}

returnStr testReturnStr2 = returnStr(GetProcAddress(dllHandler, MAKEINTRESOURCE(3)));

if (testReturnStr2 != NULL){

cout << "Mode by get function index:" << testReturnStr2() << endl;

}

else{

cout << "Can not find function printHello" << endl;

}

}

else

{

cout << "Load Library fail:" << dllName << endl;

}

}

 

int main(){

addMode();

printHelloMode();

returnStrMode();

cin.get();

}

 ③ 添加DLL文件到Debug目录(没找到Debug目录时,可以先运行一下程序,就会自动生成)

④ 工程结构

 

⑤ 运行程序,查看结果。

 

3、Dll文件不改变函数名

① 添加CreateDll.def文件

 

//CreateDll.def

LIBRARY CreateDll

EXPORTS

 

add = ?add@MyClass@MyNameSpace@@SANNN@Z

printHello = ?printHello@MyClass@MyNameSpace@@SAXXZ

returnString = ?returnString@MyClass@MyNameSpace@@SAPADXZ

 ② 重新编译后,再次查看接口名字

③ 用原来的函数名调用CreateDll.dll

//dynamicCall.cpp

#include<iostream>

#include<Windows.h>

using namespace std;

 

void addMode(){

typedef double(*add)(double number1, double number2);

char* dllName = "CreateDll.dll";

HMODULE dllHandler = LoadLibrary(dllName);

if (dllHandler != NULL){

//add testAdd = add(GetProcAddress(dllHandler, MAKEINTRESOURCE(1)));

add testAdd = add(GetProcAddress(dllHandler, "add"));

 

if (testAdd != NULL){

cout << "5.0 + 6.3 = " << testAdd(5.0, 6.3) << endl;

}

else{

cout << "Can not find function add" << endl;

}

}

else

{

cout << "Load Library fail:" << dllName << endl;

}

}

 

void printHelloMode(){

typedef void(*printHello)();

char* dllName = "CreateDll.dll";

HMODULE dllHandler = LoadLibrary(dllName);

if (dllHandler != NULL){

//通过映射函数名来使用PrintHello函数(其他两个函数同理)

printHello testPrintHello = printHello(GetProcAddress(dllHandler, "printHello"));

if (testPrintHello != NULL){

testPrintHello();

}

else{

cout << "Can not find function printHello" << endl;

}

}

else

{

cout << "Load Library fail:" << dllName << endl;

}

}

 

void returnStrMode(){

typedef char(*returnStr)();

char* dllName = "CreateDll.dll";

HMODULE dllHandler = LoadLibrary(dllName);

if (dllHandler != NULL){

//两种方法实现returnStr

returnStr testReturnStr = returnStr(GetProcAddress(dllHandler, "returnString"));

if (testReturnStr != NULL){

cout << "Mode by get function name:" << testReturnStr() << endl;

}

else{

cout << "Can not find function returnString" << endl;

}

returnStr testReturnStr2 = returnStr(GetProcAddress(dllHandler, MAKEINTRESOURCE(3)));

if (testReturnStr2 != NULL){

cout << "Mode by get function index:" << testReturnStr2() << endl;

}

else{

cout << "Can not find function returnString" << endl;

}

}

else

{

cout << "Load Library fail:" << dllName << endl;

}

}

 

int main(){

addMode();

printHelloMode();

returnStrMode();

cin.get();

}

④ 可以去除多余接口(由图可以看出接口翻倍了,但地址没变,现在清除函数名已被更改的接口,只要把myDll.h__declspec(dllexport)去掉即可

//myDll.h

#ifdef MYDLL_EXPORTS  

#define MYDLL_API   

#else  

#define MYDLL_API    

#endif 

 

namespace MyNameSpace{

class MyClass

{

public:

static MYDLL_API void printHello();

static MYDLL_API double add(double number1, double number2);

static MYDLL_API char* returnString();

};

}

⑤ 再次查看接口

 

⑥ 调用同理(略)