發表文章

目前顯示的是 8月, 2021的文章

C++ dll動態程式庫建置架構筆記(CMake build) -5 如何使用LoadLibraryA()讀取class架構dll

上一篇介紹dll裡建立class,但他是使用header.h+.lib+.dll方式讀取dll程式,這篇要講解我如何使用LoadLibraryA()讀取,先說程式碼會很多,因為要把整個class重新改寫成function型式,這方法應該能讓C++ dll程式在C語言上執行。這其實是我一開始學習建置dll的方式,順便紀錄一下,可能還有更好的方式我還沒研究到。 一、void pointer說明 這個功能很強大,他可以指向所有資料型態的指標,我這邊把他拿來指向整個class。在外部使用的人只會看到這是一個void pointer,不知道他其實是一個class,所以可以將整個class隱藏在dll內部。 二、建立class指標 假如有一個 class 名稱是 foo。 class foo { void Add(int b); ... }; 使用 void pointer 指標指向 class。 //create void pointer typedef void* foo_handle; //void pointer指標指向新建立的class foo_handle foo_h = (foo_handle)new foo(); 三、刪除空指標裡的class 當 class 不再使用時,或程式結束時,要將佔用的資源釋放,pointer 要指向 NULL,因為通常會檢查這個指標如果非 NULL 表示指向的 class 還存在著。 //刪除class delete (foo*)foo_h; //將void pointer 指向空 foo_h = NULL; 四、在dll裡建立\刪除class 我這邊使用 extern "C" __declspec(dllexport) 建立dll function。 typedef void* foo_handle; extern "C" __declspec(dllexport) foo_handle createClass() { return (foo_handle)new foo(); } extern "C" __declspec(dllexport) int des

C++ dll動態程式庫建置架構筆記(CMake build) -4 如何使用class架構

其實這部分我還沒研究的很深入,只先將我所知道的部分記錄下來。 我主要會針對在 class 裡需要儲存變數的做法說明,最常見的情況就是 class 裡面會暫時儲存一些資料給多個 funciton 使用,他們的資料型態可能是 C++ 原有的,也可能是自己定義的 struct,再來考慮到這些資料型態是僅內部使用還是要傳出給外部使用等各種可能的情況。 一、使用情況 第1種情況 : 暫存變數是 C++ 資料型態,可在 class 內部及外部使用。 只要使用的人也有這些資料型態的定義就可以,假如其中有一個型態使用的人無法知道,就要附加上,如果無法附加上那只能用以下方法將它隱藏在內部,自己寫一個轉譯的 function 傳送出去。 第2種情況 : 暫存變數非 C++ 資料型態,僅在class內部使用。 第3種情況 : 暫存變數非 C++ 資料型態,需將資料傳出使用。 之後我使用以下的架構,struct newNumber 在2、3種方法裡當作非 C++ 變數 struct newNumber { int i; int j; }; class math_class { public: newNumber a; math_class(int val) { a.i=val; a.j=val*10; } void Add(int b) { a.i+=b; a.j+=b; } }; 二、做法及範例 第1種情況 可以用比較簡單作法,相似於 第一篇文章 的寫法,因為 struct 本身及 struct 內部都使用 C++ 資料型態,使用的人都知道這些資料型態,只要這個 struct 使用的人也有定義就好。以下用第2種實作範例: 最外層的header.h,編譯完能給使用者匯入的 Dll_class_c\math_class\include\my_math_class_c.h #ifndef my_math_H_ #define my_math_H_ #include "SVdef.h" struct newNumber { int i; int j; }; class SV_EXPORTS math_class {

C++ dll動態程式庫建置架構筆記(CMake build) -3 建立兩層(多層)dll程式

寫這系列筆記主要就是為了要記錄"如何建立多層 dll 程式"的做法而生,網路上看到很少有人說明 dll 去使用 dll 的做法怎麼做,也可能沒輸入到對的關鍵字,雖然其實學會編譯 dll 及使用執行程式測試做出來的 dll,就可能已經大概知道怎麼建立兩層以上的 dll,但我本人就是沒有那個慧根,也可能是因為我一開始是學 LoadLibraryA() 匯入 dll 檔的作法,以至於覺得第二層也是要這樣讀取很複雜,為了探討怎麼輕鬆的做出多層 dll 程式,才有這篇文章。 一、架構說明 Dll_1Layer_math.dll 內容: 建立一個簡單的 dll 數學運算程式,加減乘除等...。 Dll_2Layer_tool.dll 內容: 重新建立函數名稱,使用 Dll_1Layer_math.dll 內函數。 test.exe 內容: 測試 Dll_2Layer_tool.dll 內的函數。 編譯順序: Dll_1Layer_math.dll → Dll_2Layer_tool.dll → test.exe  二、建議作法 學習了兩種匯入 dll 的方式後,我發現使用 LoadLibraryA() 比較繁瑣,在重寫函數名稱時容易出錯,修改上也比較麻煩,所以我覺得在必要時才去使用這個做法。 Dll_2Layer_tool.dll → test.exe: 建議兩種做法都可以:1. LoadLibraryA() 2. header.h+.lib+.dll Dll_1Layer_math.dll → Dll_2Layer_tool.dll: 建議做法 header.h+.lib+.dll 三、實作Dll_2Layer_tool.dll Dll_1Layer_math.dll 的實作我寫在 第一篇文章 。 檔案結構: 根目錄 ├─common │ └─SVdef.h ├─Dll_2Layer │ ├─main │ │ ├─test.cpp │ │ └─CMakeFiles.txt │ ├─tool │ │ ├─include │ │ │ └─tool_API.h │ │ └─src │ │ └─tool_API.cpp │ └─CMakeF

C++ dll動態程式庫建置架構筆記(CMake build) -2 如何使用dll程式

這篇介紹如何讀取及使用 C++ 動態程式庫。 我的系統環境: Win10 CMake 3.18.4 VisualStudio 2019 一、介紹做法 我所知道的有兩種做法: 1.需要header、lib檔     優點:程式碼較少、不用重寫定義     缺點:還不知道 2.只需要dll檔     優點:可在程式執行中期匯入及釋放      缺點:程式碼較繁瑣、使用的人要知道 dll 裡面的 function 名稱及參數架構 二、說明 作法一、需要header、lib檔 需要 include dll 程式提供給外部使用的 function 定義檔,也就是有加 __declspec(dllexport) 的部分。 以下是使用 上一篇文章 所做出來的 dll 程式。 test.cpp #include <stdio.h> #include "my_math.h" int main() { int a = 10; int b = 20; int res = Add(a,b); printf("Add %d\n", res); res = Subtraction(a,b); printf("Subtraction %d\n", res); res = Multiply(a,b); printf("Multiply %d\n", res); math_class math_cls; res = math_cls.Add(a,b); printf("math_class Add %d\n", res); res = math_cls.Subtraction(a,b); printf("math_class Subtraction %d\n", res); res = math_cls.Multiply(a,b); printf("math_class Multiply %d\n", r

C++ dll動態程式庫建置架構筆記(CMake build) -1 dll程式寫法

這篇介紹如何建置一個基本的 C++ 動態程式庫。 我的系統環境: Win10 CMake 3.18.4 VisualStudio 2019 一、程式寫法差異 1.一般的寫法 my_math.h int Add(int a, int b); class math_class { public: int Add(int a, int b); }; my_math.cpp int Add(int a, int b) { return a+b; } int math_class::Add(int a, int b) { return a+b; } 2.dll的寫法 在需要提供給外部使用的 function 或是 class 加上 __declspec(dllexport) ,告訴編譯器這是能提供給外部使用的 API 介面。 my_math.h extern "C" __declspec(dllexport) int Add(int a, int b); class __declspec(dllexport) math_class { public: int Add(int a, int b); }; my_math.cpp int Add(int a, int b) { return a+b; } int math_class::Add(int a, int b) { return a+b; } extern "C" 探討 我看其他人講解應該是能讓程式在 C 與 C++ 之間混用,如果都是 C++ 環境是不是就可以不用寫,這部分我不是很清楚,求大神解惑了。 我覺得應該是將 C++ 轉為 C 語言的格式,能讓 C++ dll 程式在 C 語言上執行,因為曾經在 function 參數的部分使用 std::string 資料型態,結果使用這個 dll 的人說他無法讀到 std::string 裡面的資料,須注意可能只能使用 C 語言有的資料型態。 二、實作 檔案架構 根目錄 ├─common │ └─SVdef.h ├─Dll_1Layer │