隨著需求不斷增加,發現好像需要更多的東西了。在官網上找不到資料,四處拼湊才有了本文的分享。
上一文(DLang 與 C 語言互動(一) - jeefy - 部落格園)中說了非常簡單了例子。本文試著向更高階的方法拓展。
文章連結(防止機器搬運):https://www.cnblogs.com/jeefy/p/17503853.html
對,還是它,只是這次給出更多的解決思路。
在 Writing Shared Libraries With D On Linux - D Programming Language 中我看到了這個命令:dmd -oflibdll.so dll.o -shared -defaultlib=libphobos2.so -L-rpath=/path/to/where/shared/library/is
其中 -L...
後面跟的東西叫做 linkflag
,會在連結的時候使用。
於是對於一個程式,我們可以通過:
dmd somefiles.d -L-lsomelib -L-rpath=/additional/path/to/search/for/lib
來設定連結庫。
其中
-rpath=...
的意思可以參考:GCC 中 -L、-rpath和-rpath-link的區別 - lsgxeva - 部落格園
於是在我的專案 Jeefy / jimg · GitLab 中,最終的編譯命令為:
dmd ./src/main.d -of=./build/main -I./src -L-L./build -L-rpath=./build -L-ljimg
編譯前在
build
目錄下有一個libjimg.so
檔案。我通過此命令連結到這個庫。
那麼接下來的問題在於轉化為我如何將多個 dlang 檔案編譯成一個 .so
檔案。
這裡設 OBJS
表示所有預編譯後的檔案(.o
)。
有如下命令(採用的是 Makefile
的語法表達):
dmd $(OBJS) -shared -fPIC -of=libtest.so -L-lsomelib
我成功的獲得了一個可以使用的庫。
利用 ldd libtest.so
檢視依賴,可以發現所有的 -l...
的依賴都被加入其中。
也就是說我可以把一個模組以及其依賴打包成一個 shared library
然後通過 -L-l...
來連結它。
這是唯一的方法嗎?並不是的。
事實上採用 gcc/g++
也可以。與上面類似:
gcc $(OBJS) -shared -fPIC -o libtest.so -lsomelib -DSOME_MACRO
可以得到一樣的結果,並且我還可以定義一些宏傳入其中。也就是說實際 gcc
可能功能更齊全。但是如果其中包含了沒有預編譯過的 .d
檔案,就只能使用 dmd
達到這種效果了。
需要偵錯?不知道用什麼偵錯?利用專門寫給 dlang 的工具偵錯發現對 C 的支援不好?
於是轉身向 gdb 走去。
想要開啟偵錯功能,則需要在編譯的時候加入 -g
引數。
無論是dmd還是gcc都要。之後通過 gdb 偵錯即可。
命令,斷點什麼的和一般的偵錯是一模一樣的。不多說了。
在 Writing Shared Libraries With D On Linux - D Programming Language 中有眾多講解,這裡提兩句。
在 dlang 中載入連結庫需要用到 core.sys.posix.dlfcn
,這相當於 #include <dlfcn.h>
。也就是說,dlang 中載入動態庫的程式碼與 C 中幾乎一模一樣。
這裡不妨以 dlang 載入 dlang 的庫為例。
lib.d 編譯為連結庫,main.d 中載入。
dmd -c lib.d -fPIC
dmd -oflibtest.so lib.o -shared -defaultlib=libphobos2.so
dmd -c main.d
dmd main.o -L-ltest -L-L. -defaultlib=libphobos2.so -map
-defaultlib=libphobos2.so
是否是必要的取決於連結的物件。加上它之後的區別在於
libtest.so, main
會新增動態的對於libphobos2.so
的依賴。可以通過ldd
檢視。也就是是靜態連結和動態連結的區別。如果是在 dlang 中載入 dlang 的庫,那麼是必要的,否則,會有多個 dlang 的範例在執行,產生衝突。(
Otherwise, the result will be multiple instances of the D runtime conflicting with each other.
)反正只要不是多個 dlang 庫間呼叫,那麼就要用
-defaultlib=libphobos2.so
。反之則不用。
這裡面
-map
指生成連結中的.map
檔案。具體作用請讀者自行探究。
還有幾個點說一下:
在呼叫 dlopen
和 dlclose
時,會分別呼叫的 static this() { ... }
以及 static ~this() { ... }
如果是 C 中呼叫 dlang,此時 libphobos2
會自動被開啟,不需要再手動載入一次。檔案原文 Note that libphobos2.so gets automatically dynamically loaded as well.
....
有一段時間我瘋狂吐槽 dlang,僅僅是因為我當時認為其對 C/C++ 的支援很爛(在嘗試寫 jgui 的時候),如此接近 C 系列的語言竟然這樣!然後我就沒有如何看 dlang 這個東西。
後來我機緣巧合之下,看到了 quandim
專案。於是我就想實現類似的功能,於是開始寫 Jeefy / jimg · GitLab 接著就探索到了本文中的內容。確實機緣巧合令人驚歎。
接著發現一點中文檔案都沒有……全是英文。幸虧我英語不錯,看這些檔案還是沒有問題。所以才有了這些文章。
哎,幸虧是高中生,不然真可能直接擺爛,然後放棄 dlang。
說實話,dlang 還是非常好的一種語言,雖然其 class
的記憶體分配是真的弱智……就不能同時 new
多個物件,一起分配空間嗎 QwQ