2010-08-23 15 views
9

En algunos de los tutoriales de LLVM me veo donde es bastante fácil enlazar la función C en un lenguaje personalizado basado en LLVM. LLVM le da al programador un puntero a la función que luego puede mezclarse con el código que está generando LLVM.LLVM enlace automático de C++

¿Cuál es el mejor método para hacer esto con las bibliotecas C++. Digamos que tengo una biblioteca bastante compleja como Qt o Boost que quiero vincular a mi idioma personalizado. ¿Necesito crear una biblioteca de stub (como Python o Lua require), o LLVM ofrece algún tipo de interfaz de función foránea (FFI)?

Respuesta

12

En mi código LLVM, creo extern "C" funciones de envoltura para esto, e inserte declaraciones de funciones LLVM en el módulo para llamarlas. Entonces, una buena manera de hacer que LLVM conozca las funciones es no dejarlo usar dlopen y buscar el nombre de la función en el binario de ejecución (esto es un dolor en el culo, ya que los nombres de las funciones deben estar en la sección .dynsym, y también es lento), pero para hacer la asignación manualmente, usando ExecutionEngine::addGlobalMapping.

acaba de obtener el llvm::Function* de esa declaración y la dirección de la función como se indica en C++ por &functionname convertido a void* y pasan a lo largo de estas dos cosas a LLVM. El JIT que ejecuta tus cosas sabrá dónde encontrar la función.

Por ejemplo, si desea envolver QString puede crear varias funciones que crean, destruyen y se llaman a las funciones de un objeto tal

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

y crear declaraciones apropiadas y un mapeo. Luego puede call estas funciones, pasando a lo largo de una región de memoria convenientemente alineada y dimensionada para QString (posiblemente alloca 'ed) y una i8* apuntando a los datos de cadena C para la inicialización.

+0

Obtiene la respuesta para proporcionar ejemplos de código conciso. ¡Gracias! Exactamente lo que estaba buscando. –

3

Si compila un código en C++ y otro en otro idioma para el código de bits LLVM, debería ser perfectamente posible vincularlos entre sí y dejar que uno llame al otro ... en teoría.

En la práctica, necesitará un código de pegamento para convertir entre los diferentes tipos de idioma (por ejemplo, no hay equivalente a una cadena Python en C++ a menos que use CPython, por lo que para void reverse(std::string s) debe llamarse str necesita una conversión - peor, todo el modelo de objetos es muy diferente). Y Qt específicamente tiene mucha magia que puede requerir mucho más esfuerzo para exponer después de compilaciones. Además, puede haber más problemas potenciales de los que no estoy enterado.

E incluso si eso funciona, es potencialmente muy feo de usar. Todavía hay funciones get* y set* en todo PyQt a pesar de las descripciones muy prácticas de Python, y se hicieron muchos esfuerzos en PyQt, no solo crearon algunos stubs.

Cuestiones relacionadas