VS2013創建與使用DLL文件(提示找不到Dll函數解決辦法)


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();

};

}

⑤ 再次查看接口

 

⑥ 調用同理(略)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM