我處于以下情況:我正在撰寫一個 C 程式,它必須動態加載一個 C 庫(即通過dlopenLinux 中的LoadLibrary和朋友以及 Windows 中的朋友)。這可以通過創建 C 介面來完成。
現在,在程式和庫中,我管理一些物件,其中包含一些指定的模板成員和一些方法:
struct MyObject {
std::vector<int> _vec;
//...
void do_something();
};
現在,如果庫是靜態加載的,我會撰寫一個庫函式,例如
void some_function(MyObject& o);
但由于它是動態加載的,我需要一些其他簽名。我在想以下內容:一個常見的標題,如
//interface.hpp
extern "C" {
void ob_w(void*);
}
struct MyObject {
//...
}
然后,在圖書館一側
//lib.cpp
#include "interface.hpp"
void ob_w(void* ptr)
{
MyObject* p = (MyObject*)ptr;
p->do_something();
}
并且,對于主程式
//main.cpp
#include "interface.hpp"
int main()
{
void* handle = nullptr;
void (*fptr)(void*);
handle = dlopen(...)
fptr = dlsym(...)
MyObject foo;
fptr((void*)&foo);
//...
}
環顧四周,我發現了其他類似的問題,但在所有這些問題中,庫都是用 C 撰寫的,因此采用了不同的解決方案。這里的庫和程式都是用 C 撰寫的,void 指標只是為了避免一些配接器。我想知道我的方法是否正確(我在 linux 機器上嘗試過,似乎給出了正確的結果)和安全。如果不是,我怎么能在不引入任何開銷的情況下傳遞物件的指標(例如某些配接器)?
uj5u.com熱心網友回復:
將我的評論提升為一個答案:如果您樂于需要 C ,您絕對不需要更改函式的簽名以使其與動態鏈接一起作業。也就是說,以下作業:
extern "C" void some_function(MyObject& o) {
o.do_something();
}
然后你可以有一個main.cpp如下(片段):
void* lib = dlopen("myobject.so", RTLD_LAZY);
if (not lib) fail_spectacularly();
void (*some_function)(MyObject&) = reinterpret_cast<decltype(some_function)>(dlsym(lib, "some_function"));
if (not some_function) fail_spectacularly();
MyObject obj = whatever;
some_function(obj);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/388769.html
