[英]Best practice for C++ program with plugins in Linux
有人可以了解將插件加載到C ++ Linux程序的最佳做法是什么?
假設我們有一個帶插件的程序(編輯器)(libsyntax.so)。 編輯器的配置文件包含libsyntax.so庫的路徑(plugin1 = / opt / editor / gizmos / libsyntax.so)。 編輯器讀取配置然后調用:
void* library = dlopen(path, RTLD_NOW|RTLD_GLOBAL);
MYFUN* function = (MYFUN*)dlsym(library, "function");
一切都很好,東西很有效。
現在讓我們假設(libsyntax.so)依賴於輔助庫(libcolor.so)。 當我們運行readelf時,我們得到:
readelf -d libsyntax.so
Dynamic section at offset 0x12b6b48 contains 31 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libcolor.so]
...
但是此時上面的dlopen()失敗了,錯誤是“沒有這樣的文件或目錄”。 使用LD_DEBUG = all顯示加載libsyntax.so后,消息為:
28664: file=libcolor.so [0]; needed by /home/.../libsyntax.so [0]
28664: find library=libcolor.so [0]; searching
28664: search cache=/etc/ld.so.cache
28664: search path=/lib64/tls/x86_64:/lib64/tls:...:/usr/lib64 (system search path)
28664: trying file=/lib64/tls/x86_64/libcolor.so
... and so on
加載器/鏈接器在標准位置查找,顯然,沒有找到我的依賴項。 這可以通過ldconfig或LD_LIBRARY_PATH輕松處理,但兩個解決方案都很臟。
是否有一種干凈的方式來加載插件和依賴項? 你好嗎?
確保依賴關系的一種干凈方法是在將程序及其插件鏈接到可以找到依賴關系的合理位置期間設置運行時搜索路徑( RPATH )。
如果rpath設置為二進制文件(您可以使用readelf
),則鏈接器將使用除默認系統位置和LD_LIBRARY_PATH
之外的其他路徑。
另外,還有一個特殊的變量$ORIGIN
,它總是在運行時解析為當前二進制文件的位置,你可以設置相對於它的路徑!
例如,如果您的應用程序的根路徑(包含主可執行文件)是/opt/editor
,則插件位於/opt/editor/gizmos
,假設您有另一個文件夾, /opt/editor/lib
具有其他依賴項,您可以使用鏈接器選項:
# editor executable
-Wl,-rpath=$ORIGIN/lib
# plugins
-Wl,-rpath=$ORIGIN/../lib,-rpath=$ORIGIN
我認為LD_LIBARY_PATH在這里是你的朋友。 只需定義插件接口的定義,插件所需的庫應該位於哪里,並確保在程序中將LD_LIBARY_PATH設置為該位置。
在調用dlopen之前簡單地設置它應該足以加載庫。 程序中不需要進行任何其他更改,也不需要插件本身的特殊鏈接。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.