2010-08-23 6 views
9

Dans certains des tutoriels LLVM je suis vu où il est assez facile de lier la fonction C dans un langage personnalisé basé sur LLVM. mains LLVM le programmeur d'un pointeur vers la fonction que l'on peut ensuite être mélangé à l'aide du code étant généré par LLVM.LLVM C++ automatique reliant

Quelle est la meilleure méthode pour le faire avec les bibliothèques C++. Disons que j'ai une bibliothèque assez complexe comme Qt ou Boost que je veux lier à ma langue personnalisée. Ai-je besoin de créer une bibliothèque stub (comme Python ou Lua besoin), ou ne LLVM offre une sorte d'interface de fonction étrangère (FFI)?

Répondre

12

Dans mon code LLVM, je crée des fonctions wrapper extern "C" pour cela, et j'insère des déclarations de fonctions LLVM dans le module pour les appeler. Ensuite, un bon moyen de faire connaître LLVM sur les fonctions est de ne pas le laisser utiliser dlopen et de chercher le nom de la fonction dans le binaire en cours d'exécution (cela est pénible car les noms des fonctions doivent être dans la section .dynsym, et il est trop lent), mais pour faire le mappage manuellement, en utilisant ExecutionEngine::addGlobalMapping.

Procurez-vous le llvm::Function* de cette déclaration et l'adresse de la fonction donnée en C++ par &functionname converti en void* et passer ces deux choses le long de LLVM. Le JIT exécutant vos trucs saura alors où trouver la fonction.

Par exemple, si vous vouliez envelopper QString vous pouvez créer plusieurs fonctions qui créent, détruisent et appellent des fonctions d'un tel objet

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(); 
} 

et de créer des déclarations appropriées et une cartographie. Ensuite, vous pouvez call ces fonctions, en passant le long d'une région de mémoire convenablement alignés et dimensionnés pour QString (éventuellement alloca 'ed) et un i8* pointant vers les données de chaîne C pour l'initialisation.

+0

Obtient la réponse pour fournir des exemples de code concis. Merci! exactement ce que je cherchais. –

3

Si vous compilez un code en C++ et certains dans une autre langue à LLVM code binaire, il devrait être parfaitement possible de les relier ensemble et laisser un appel l'autre ... en théorie. En pratique, vous aurez besoin de code de colle pour convertir entre les différents types de langage (par exemple, il n'y a pas d'équivalent à une chaîne Python en C++ sauf si vous utilisez CPython, donc void reverse(std::string s) pour être appelable avec str vous avez besoin d'une conversion - pire, le modèle d'objet entier est très différent). Et Qt a en particulier beaucoup de magie qui peut nécessiter beaucoup plus d'efforts pour s'exposer après les compilations. En outre, il peut y avoir d'autres problèmes potentiels que je ne connais pas.

Et même si cela fonctionne, il est potentiellement très moche à utiliser. Il y a encore get* et set* fonctions sur PyQt malgré les descripteurs très pratiques de Python - et beaucoup d'efforts sont allés dans PyQt, ils n'ont pas seulement créé des stubs.