es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo puedo utilizar wasm-bindgen desde un programa compilado con Emscripten?

Estoy intentando vincular una biblioteca de Rust que contiene código generado por wasm-bindgen con un programa escrito en C que me gustaría compilar con Emscripten. Mi MRE es el siguiente:

En el lado de Rust, tengo Cargo.toml:

[package]
name = "rust_project"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["staticlib"]

[dependencies]
wasm-bindgen="0.2"

y en lib.rs tengo:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

#[no_mangle]
pub extern "C" fn call_from_c() {
    log("Hello, World!");
}

Como primer paso, compilo esto con cargo build --target wasm32-unknown-unknown, lo cual produce un librust_project.a. Luego, configuro el siguiente proyecto en C con main.c:

/* Declarar la función de Rust */
void call_from_c();

/* Llamar a la función desde main */
int main() {
    call_from_c();
    return 0;
}

y CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
project(c_project)
add_executable(c_project main.c)
target_link_libraries(c_project /path/to/librust_project.a)

Finalmente, intento juntarlo todo utilizando la herramienta Emscripten de la siguiente manera:

cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/Emscripten.cmake ../
make

Aquí es donde algo parece salir mal en la etapa de enlace, ya que emcc informa que __wbg_log_941ab916ed5a24bd es un símbolo indefinido. Sospecho que este símbolo (entre otros) se está eliminando como parte de un esfuerzo de optimización, pero no estoy seguro en qué etapa ni cómo puedo desactivar esta optimización.

Agregar las siguientes opciones de enlazador en CMake resulta en una compilación con una advertencia sobre el símbolo indefinido:

target_link_libraries(c_project
    /path/to/librust_project.a
    "-s EXPORTED_FUNCTIONS=[\"_main\",\"___wbg_log_941ab916ed5a24bd\"]"
    "-s ERROR_ON_UNDEFINED_SYMBOLS=0"
)

Pero creo que estos símbolos faltantes son problemáticos y cuando ejecuto wasm-bindgen (la herramienta de línea de comandos) en c_project.wasm, obtengo el siguiente error:

import of `__wbg_log_941ab916ed5a24bd` doesn't have an adapter listed

¿Cómo puedo evitar que las funciones importadas/exportadas de wasm-bindgen sean eliminadas durante este proceso?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para evitar que las funciones importadas/exportadas de wasm-bindgen sean eliminadas durante el proceso de enlace, puedes utilizar la bandera del enlazador --import-memory y agregar extern wasm_bindgen::__wbindgen_malloc, extern wasm_bindgen::__wbindgen_free a la lista de funciones exportadas.

    Para lograr esto, puedes modificar tu archivo CMakeLists.txt de la siguiente manera:

    cmake_minimum_required(VERSION 3.5)
    project(c_project)
    
    # Establecer la arquitectura objetivo como wasm32
    set(CMAKE_C_FLAGS "-m32 -march=native")
    set(CMAKE_CXX_FLAGS "-m32 -march=native")
    set(CMAKE_EXE_LINKER_FLAGS "-m32 -march=native")
    
    # Establecer la herramienta de compilación como Emscripten
    SET(CMAKE_C_COMPILER emcc)
    SET(CMAKE_CXX_COMPILER em++)
    
    add_executable(c_project main.c)
    
    # Enlazar la biblioteca Rust con el proyecto C
    target_link_libraries(c_project
      /ruta/hacia/librust_project.a
      "--import-memory"
      "-s EXPORTED_FUNCTIONS=['_main','__wbg_log_941ab916ed5a24bd','_malloc','_free']")
    
    # Especificar la extensión y formato del archivo de salida
    set_target_properties(c_project
      PROPERTIES
      SUFFIX ".html"
      LINK_FLAGS "-s WASM=1 -s SIDE_MODULE=0")
    

    Este archivo CMakeLists.txt establece la arquitectura objetivo en wasm32 y la herramienta de compilación en Emscripten. El comando target_link_libraries incluye la bandera del enlazador --import-memory y exporta las funciones necesarias de wasm-bindgen (__wbg_log_941ab916ed5a24bd, __wbindgen_malloc y __wbindgen_free) además de la función main. Por último, el comando set_target_properties establece la extensión y formato del archivo de salida como HTML y WebAssembly, respectivamente.

    Con estas modificaciones, la biblioteca Rust que contiene el código generado por wasm-bindgen debería enlazarse correctamente con el programa C, y las funciones importadas/exportadas de wasm-bindgen no deberían eliminarse durante el proceso de enlace.

Comments are closed.