将C++库链接到WASI环境下Rust代码时遇_ZdlPv未定义错误
问题分析
env::_ZdlPv是C中operator delete(void*)的符号混淆(mangled)名称,这个错误说明你的WASM模块缺少C标准库的实现。你在build.rs中使用了.cpp_link_stdlib(None),完全禁用了C标准库的链接,但代码中使用的std::string和OpenXLSX::XLXmlData类型,其构造、析构过程会调用内存分配/释放函数(new/delete),而这些函数属于C标准库,因此出现了未定义的导入符号。
解决方案
1. 恢复C++标准库链接
移除build.rs中所有.cpp_link_stdlib(None)的调用,让cc crate自动链接WASI兼容的C标准库。如果自动链接不生效,可以手动指定链接libc:
.cpp_link_stdlib("c++")
同时,WASI环境对C++异常支持有限,建议添加编译标志禁用异常和RTTI(OpenXLSX通常不需要这些特性):
.flag("-fno-exceptions") .flag("-fno-rtti")
2. 修改后的build.rs示例
use std::env; fn main() { cc::Build::new() .cpp(true) .flag("-std=c++17") .flag("-stdlib=libc++") .flag("-fno-exceptions") .flag("-fno-rtti") .archiver("llvm-ar") .include("OpenXLSX/external/pugixml") .include("OpenXLSX/external/nowide") .include("OpenXLSX/external/zippy") .include("OpenXLSX/headers") .include("OpenXLSX") .flag("--sysroot=/opt/wasi-sysroot") .flag("-fvisibility=default") .file("OpenXLSX/sources/XLCell.cpp") .file("OpenXLSX/sources/XLCellIterator.cpp") .file("OpenXLSX/sources/XLCellRange.cpp") .file("OpenXLSX/sources/XLCellReference.cpp") .file("OpenXLSX/sources/XLCellValue.cpp") .file("OpenXLSX/sources/XLColor.cpp") .file("OpenXLSX/sources/XLColumn.cpp") .file("OpenXLSX/sources/XLContentTypes.cpp") .file("OpenXLSX/sources/XLDateTime.cpp") .file("OpenXLSX/sources/XLDocument.cpp") .file("OpenXLSX/sources/XLFormula.cpp") .file("OpenXLSX/sources/XLProperties.cpp") .file("OpenXLSX/sources/XLRelationships.cpp") .file("OpenXLSX/sources/XLRow.cpp") .file("OpenXLSX/sources/XLRowData.cpp") .file("OpenXLSX/sources/XLSharedStrings.cpp") .file("OpenXLSX/sources/XLSheet.cpp") .file("OpenXLSX/sources/XLWorkbook.cpp") .file("OpenXLSX/sources/XLXmlData.cpp") .file("OpenXLSX/sources/XLXmlFile.cpp") .file("OpenXLSX/sources/XLZipArchive.cpp") .file("OpenXLSX/external/pugixml/pugixml.cpp") .compile("OpenXLSX"); cc::Build::new() .archiver("llvm-ar") .cpp(true) .flag("-stdlib=libc++") .flag("-fno-exceptions") .flag("-fno-rtti") .flag("-fvisibility=default") .flag("-std=c++17") .include("OpenXLSX/external/pugixml") .include("OpenXLSX/headers") .include("OpenXLSX") .flag("--sysroot=/opt/wasi-sysroot") .file("mylib.cpp") .compile("libmylib.a"); }
3. CMake方案补充
如果使用CMake生成OpenXLSX的WASM静态库,需要在CMakeLists.txt中指定正确的WASI目标,并启用C++标准库链接:
set(CMAKE_SYSTEM_NAME WASI) set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -fno-exceptions -fno-rtti") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
生成静态库后,在Rust的build.rs中除了链接OpenXLSX,还要确保链接C++标准库:
println!("cargo:rustc-link-lib=static=c++"); println!("cargo:rustc-link-lib=static=OpenXLSX"); println!("cargo:rustc-link-search=native={}/wasm-libs", src_dir);
4. Bindgen重复定义问题处理
Bindgen出现重复定义通常是因为OpenXLSX的头文件中存在全局符号或重复声明。可以通过以下方式缓解:
- 使用
--hide-type或--hide-function排除不需要的符号 - 在Bindgen配置中设置
blocklist_item过滤重复定义的符号 - 确保OpenXLSX的头文件使用
#pragma once或include guard避免重复包含
内容的提问来源于stack exchange,提问作者Kival M
相关产品推荐
相关产品推荐

