跳到主要內容

發表文章

目前顯示的是 4月, 2017的文章

Dynamically loaded libraries 動態載入庫 #3 C++ 類別載入

Dynamically loaded libraries 動態載入庫 #3 C++ 類別載入 繼上一篇 Dynamically loaded libraries 動態載入庫 #2 C++ 提到 libdl 是 C 函式庫,不包含類別的功能, 而 C++ 物件導向的特性之一 多形 可以用來達成動態載入類別的功能, 這樣唯一不足的點是, 在要使用動態類別庫的專案中需要加入類別介面標頭, 而不能在讓編譯器完全不知道類別介面的狀況下動態載入。 範例類別庫 以下程式為了節省版面沒有使用 #include 防範 HelloWorld.hpp (介面) class HelloWorld { public: HelloWorld() {} virtual ~HelloWorld() {} virtual void hello() {} }; extern "C"{ HelloWorld* create_object(); void destroy_object(HelloWorld* object); } 會直接實作 HelloWorld 的方法是為了使用上的方便, 不論是不實作或是讓它=0都會有些相對應的問題, 因此我還是將這個 HelloWorld 稱為介面。 create_object 和 destroy_object 兩個函式用於轉發建構子與解構子, 這下就有辦法呼叫其他類別庫中的 HelloWorld 子類別建構子、解構子, 也剛好有 HelloWorld 介面,如此就可以動態載入類別了。 MyHelloWorld.hpp (要被動態載入的類別) #include "HelloWorld.hpp" class MyHelloWorld: public HelloWorld { public: MyHelloWorld(); virtual ~MyHelloWorld(); virtual void hello(); }; MyHelloWorld.cpp #include "MyHelloWorld.hpp" #include <iostream> /* 轉發建構子*/ HelloWor

Dynamically loaded libraries 動態載入庫 #2 C++

Dynamically loaded libraries 動態載入庫 #2 C++ 繼上一篇 Dynamically loaded libraries 動態載入庫 這篇寫如何寫C++的動態載入庫,因為C++編譯器會修飾函式名稱,所以不能直接用C的方式寫庫 範例函式庫 mylib.h extern "C" { void hello(); void world(); } 與C的不同處是這裡要加上 extern "C" {} 包住不希望被編譯器修飾的函式 hello.cpp #include "mylib.h" #include <iostream> void hello(){ std::cout << "Hello" ; } world.cpp #include "mylib.h" #include <iostream> void world(){ std::cout << "World" ; } 編譯 $ g++ -c -fPIC hello.cpp world.cpp $ g++ -shared -o libmylib.so hello.o world.o 編譯的方式除了從gcc改為g++之外,沒有其他改變 使用方式 main.cpp int main() { void* handle = dlopen("./libmylib.so", RTLD_LAZY); void (*f1)() = (void (*)()) dlsym(handle, "hello"); void (*f2)() = (void (*)()) dlsym(handle, "world"); f1(); f2(); dlclose(handle); return 0; } 使用方式和C一模一樣,這裡假設不會出錯誤 編譯 編譯時要一樣連結 libdl,使用 -ldl $ g++ main.cpp -ldl

Dynamically loaded libraries 動態載入函式庫

Dynamically loaded libraries 動態載入庫 動態載入函式庫可以由程式控制在需要時才載入、釋放,在編譯連結時不需要相關的界面與函式庫,可以用來設計軟體插件之類的功能。 範例函式庫 mylib.h void hello(); void world(); hello.c #include "mylib.h" #include <stdio.h> void hello(){ printf("Hello"); } world.c #include "mylib.h" #include <stdio.h> void world(){ printf("World"); } 編譯 $ gcc -c -fPIC hello.c world.c $ gcc -shared -o libmylib.so hello.o world.o -fPIC 要編譯器產生 position-independent code -shared 編譯 Shared Library -o libmylib.so 函式庫檔案名稱為 libmylib.so 這裡沒使用 soname 等便於版本維護的參數 這樣會建立一個 libmylib.so 共享函式庫 使用方式 main.c #include <dlfcn.h> /* 動態載入要用的相關函式標頭 */ #include <stdio.h> int main() { /* 載入函式庫 libmylib.so */ void* handle = dlopen("./libmylib.so", RTLD_LAZY); /* 若有錯誤可以取得錯誤訊息 */ char* err = dlerror(); if (err) { printf(err); return 0; } /* 取得void hello()函式的指標 */ void (*f1)() = (void (*)()) dlsym(handle