2010-08-23 50 views
9

在一些LLVM教程,我看到它是相當容易的C函數綁定到基於LLVM的自定義語言。 LLVM向程序員傳遞一個指向該函數的指針,該函數可以與LLVM生成的代碼混合在一起。LLVM自動C++鏈接

什麼是與C++庫做到這一點的最好方法。假設我有一個相當複雜的庫,比如Qt或Boost,我想綁定到我的自定義語言。我是否需要創建存根庫(如Python或Lua需求),還是LLVM提供某種外部函數接口(FFI)?

回答

12

在我LLVM代碼,我創建extern "C"包裝函數對於這一點,並插入LLVM函數聲明爲模塊,以便給他們打電話。然後,使LLVM瞭解功能的好辦法是不要讓它使用dlopen和搜索在執行二元函數名(這是一個痛苦的屁股,因爲該函數的名稱必須是在.dynsym部分,並且速度也很慢),但要手動執行映射,請使用ExecutionEngine::addGlobalMapping

剛剛得到這個聲明和函數的地址的llvm::Function*在C++給出通過&functionname轉化爲void*並通過這兩件事情一起LLVM。執行你的東西的JIT將知道在哪裏可以找到該功能。

例如,如果你想換QString您可以創建多種功能,創造,破壞,並呼籲這樣一個對象

extern "C" void createQString(void *p, char const*v) { 
    new (p) QString(v); // placement-new 
} 

extern "C" int32_t countQString(void *p) { 
    QString *q = static_cast<QString*>(p); 
    return q->count(); 
} 

extern "C" void destroyQString(void *p) { 
    QString *q = static_cast<QString*>(p); 
    q->~QString(); 
} 

的功能和創建適當的聲明和映射。然後,您可以將這些函數沿着一個適當對齊和調整大小的存儲區傳遞給QString(可能爲alloca'ed)和一個指向C字符串數據的初始化。

+0

獲取提供簡潔代碼示例的答案。謝謝!正是我所期待的。 – 2010-08-24 12:47:21

3

如果你編譯C++和一些其他語言LLVM位碼一些代碼,它應該是完全有可能將這些理論聯繫在一起,讓一個呼叫中的其他...。在實際中,您需要粘合代碼來在不同語言的類型之間進行轉換(例如,除非使用CPython,否則在C++中沒有與Python字符串等效的內容,因此void reverse(std::string s)需要使用str進行調用,更糟的是,整個對象模型是非常不同的)。 Qt具有很多魔術,編譯後可能需要更多努力才能暴露出來。此外,我可能還有其他潛在的問題,我不知道。

即使這樣的作品,這是潛在的非常醜陋使用。儘管Python非常方便的描述符,但PyQt仍然有get*set*的功能 - 並且PyQt付出了很多努力,他們不僅創建了一些存根。