C++創建自己的庫文件(dll文件創建和編譯)


創建編譯庫文件有個好處就是不容易被修改,加密的,方便調用,但是缺點是不容易查看其中的內容,反編譯比較麻煩。下面讓我們使用VC創建編譯自己的庫文件吧。常用的函數,不常更改的,應該放到庫文件里,所以庫文件的意義非比尋常。但為了(這里需要明白C++庫和C++組件(COM組件)、插件OCX的區別) DLL與COM面試問題        DLL和插件的相關性        插件是使用了某種規則的DLL       給自己的程序添加插件功能dll做插件         DLL插件設計思想       使用DLL作為插件的設計框架        插件開發(Java)          基於插件式的開發框架            插件技術(Android)

dll庫中主要是一個函數,當然還有類和變量這些輔助對象,其主要目的是為了實現某個特定的功能,可以由任意程序調用。這跟靜態庫不同。

dll與lib的區別:lib是在編譯時和可執行程序打包到一起的,外部看不到它的存在,它在exe里面,所以如果丟失了dll它依然可以運行。它是靜態鏈接庫,是目標對象obj的集合。而dll在導出時,有時沒有lib文件,有時有lib文件,而存在的這種lib文件就是導出文件,到出庫。這樣的lib,導入文件,包含DLL導出的函數和變量的符號名,而真正的函數的實現和數據存在於DLL。lib占用內存,dll只用用時才占用內存

舉個例子:

__declspec(dllexport)

聲明一個導出函數,是說這個函數要從本DLL導出。我要給別人用。一般用於dll中省掉在DEF文件中手工定義導出哪些函數的一個方法。當然,如果你的DLL里全是C++的類的話,你無法在DEF里指定導出的函數,只能用__declspec(dllexport)導出類。

__declspec(dllimport)

聲明一個導入函數,是說這個函數是從別的DLL導入。我要用。一般用於使用某個dll的exe中不使用__declspec(dllimport)也能正確編譯代碼,但使用__declspec(dllimport)使編譯器可以生成更好的代碼。編譯器之所以能夠生成更好的代碼,是因為它可以確定函數是否存在於DLL中,這使得編譯器可以生成跳過間接尋址級別的代碼,而這些代碼通常會出現在跨DLL邊界的函數調用中。但是,必須使用__declspec(dllimport)才能導入DLL中使用的變量。

為什么叫導入文件,就是把Dll中導出的函數,類給導入到我們自己的應用程序中使用。

使用方法:1、靜態鏈接庫(lib),我們使用隱式鏈接; 2、動態鏈接庫(DLL),不包含lib導入文件,我們用顯式鏈接。但是這樣會很麻煩,我不喜歡這樣用,我會想盡方法讓它帶有lib文件。 3、動態鏈接庫(DLL),包含lib導入文件,我們使用 隱式鏈接。

 1. 新建-->項目-->Win32 Console-->勾選dll-->確定。

 2. MyDll.h頭文件聲明

#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport) //定義MYDLL_API為導出類型
#else
#define MYDLL_API __declspec(dllimport)
#endif

// This class is exported from the MyDll.dll 該類從MyDll.dll中導出
class MYDLL_API CMyDll {
public:
    CMyDll(void);
    CMyDll(int _age, char *_name); //年齡和姓名 構造函數
    ~CMyDll();
    // TODO: add your methods here.
    void Introduce(); //介紹函數
    static void SayStatic();
private:
    int age;
    char* name;
    static int a;
};

  extern MYDLL_API int nMyDll;//導出全局變量的聲明
  extern MYDLL_API float f;
  extern MYDLL_API int a;

MYDLL_API int fnMyDll(void); //導出全局函數的聲明
MYDLL_API void SayHell();
 
        

 3. MyDll.cpp文件的函數和類的實現

#include "stdafx.h"
#include "MyDll.h"
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;


// This is an example of an exported variable
MYDLL_API int nMyDll=0;
MYDLL_API float f = 3.14;
MYDLL_API int a = 23;

int CMyDll::a = 90; //全局變量

// This is an example of an exported function.
MYDLL_API int fnMyDll(void)
{
    return 42;
}
MYDLL_API void SayHell() //全局函數
{
    cout<<"Hello World!"<<endl;
}

//靜態函數
void CMyDll::SayStatic()
{
    cout<<"我是類中的靜態函數"<<endl;
    cout<<"類中靜態變量初始化值是:a="<<CMyDll::a<<endl;
}

// This is the constructor of a class that has been exported.這是已導出類的構造函數
// see MyDll.h for the class definition有關該類的定義參閱MyDll.h
CMyDll::CMyDll():name(NULL)
{
    return;
}

CMyDll::~CMyDll()
{
    if(name != NULL)
    {
        delete[]name;
    }
}

CMyDll::CMyDll(int _age, char *_name):age(0), name(NULL)
{
    this->age = _age;
    if(_name != NULL)
    {
        int len = strlen(_name)+1;
        if(name==NULL)
        {
            name = new char[len];
        }
        strcpy_s(name, len, _name);
    }
}

void CMyDll::Introduce()
{
    cout<<"My name is yujianhui"<<endl;
    cout<<"Name:"<<name<<endl;
    cout<<"Age:"<<age<<endl;
}

 項目生成如下:

 測試:(這里屬於靜態加載,即lib和dll都存在的情況下)

 步驟:1.在程序中添加頭文件;2.加載lib;3.使用。

示例:

#include<iostream>
#include "MyDll.h"
#pragma comment(lib, "MyDll")
using namespace std;

int main()
{
    cout<<a<<endl;
    cout<<f<<endl;
    SayHell();
    CMyDll mydll(24, "yujianhui");
    mydll.Introduce();
    CMyDll::SayStatic();
    system("pause");
}

 

程序下載:http://pan.baidu.com/s/1mhEqfxQ

程序介紹:VS2010版 使用方法:解壓后,使用VS打開.sln文件,然后單擊Debug->Start Without Debugging就可以看到運行結果了。因為我為了讓壓縮包變小所以刪除了過程文件,會提示你重新編譯,單擊確定即可。

 


免責聲明!

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



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