Utilizando biblioteca compartida de C++ en Idris.
Quiero utilizar FFI para acceder a una biblioteca de C++ de terceros desde Idris, pero recibo “símbolo indefinido”. Soy nuevo en la compilación de C/C++.
Estoy haciendo esto envolviendo el código C++ en una capa pura de C que llamo desde Idris. El código C++ se proporciona como un conjunto de encabezados .h y una sola biblioteca compartida .so. Actualmente solo tengo un archivo C, pero puede que tenga más más adelante.
Aquí está el encabezado de la biblioteca C++ include/foo.h:
“`c++
#include <some other/library/header.h="">
namespace mynamespace {
class Foo {
public:
Foo();
}
}
<pre><code><br />Y el envoltorio C wrapper.cpp:
“`c
#include <foo.h>
extern “C” {
struct cFoo;
using namespace mynamespace;
struct cFoo* cFoo_new() {
return reinterpret_cast<cfoo*>(new Foo());
}
}
La biblioteca compartida es lib/libfoo_ext.so y estoy compilando esto con:
g++ -shared -Iinclude -Llib -lfoo_ext -o libfoo.so wrapper.cpp
Eso funciona sin errores. Mientras tanto, el código de Idris es:
module Foo
import System.FFI
export
Foo : Type
Foo = Struct "cFoo" []
%foreign "C:cFoo_new,libfoo"
export
mkFoo : Foo
Estoy llamando a mkFoo
en un archivo de prueba. Cuando lo hago, obtengo:
Exception: (while loading libfoo.so) .../build/exec/tmpchez_app/libfoo.so: undefined symbol: _ZN17mynamespace6FooC1Ev
</cfoo*></foo.h>
davy.ai
El mensaje de error “símbolo no definido” indica que el vinculador no puede encontrar la definición para el constructor
mynamespace::Foo()
. Esto es probablemente porque el código C++ no está siendo vinculado correctamente con el código C.Una posible solución es asegurarse de que el código C++ se compile con la bandera de posición-independiente (
-fPIC
) para que pueda ser vinculado correctamente con el código C:Además, puede ser necesario incluir la biblioteca estándar de C++ al vincular:
Si esto no resuelve el problema, puede ser útil verificar que la biblioteca
libfoo_ext.so
también se compila con-fPIC
y que se incluyen los encabezados apropiados enwrapper.cpp
.Una vez que el código esté vinculado correctamente, la función
mkFoo
debería poder crear una instancia demynamespace::Foo
desde Idris.