emcc hello.cpp2个字符串相加

Gary Chen
emcc hello.cpp2个字符串相加

下面是一个使用 emcc 编译的 hello.cpp,实现 两个字符串相加(拼接) 并在 Web 前端(如 Vue/Vite 或 Electron)中调用的完整示例方案。


✅ 目标

我们用 emcc 把以下 C++ 代码编译成 wasm,并在 JS 中调用 concat("Hello, ", "World!"),得到 "Hello, World!"


🧱 Step 1:C++ 源码(hello.cpp

#include <string>
#include <cstring>
#include <cstdlib>

extern "C" {

  // 拼接两个字符串,返回新的 malloc 分配的字符串
  const char* concat(const char* a, const char* b) {
    std::string sa(a);
    std::string sb(b);
    std::string result = sa + sb;

    // 使用 malloc 分配返回值,JS 中需要手动释放(或忽略内存)
    char* cstr = (char*)malloc(result.size() + 1);
    std::strcpy(cstr, result.c_str());
    return cstr;
  }

  // 提供释放内存函数
  void free_str(char* ptr) {
    free(ptr);
  }
}

🛠️ Step 2:emcc 编译命令

emcc hello.cpp -o hello.js \
  -s EXPORTED_FUNCTIONS='["_concat", "_free_str"]' \
  -s EXPORTED_RUNTIME_METHODS='["cwrap", "UTF8ToString", "stringToUTF8", "lengthBytesUTF8", "allocateUTF8"]' \
  -s MODULARIZE=1 \
  -s EXPORT_ES6=1 \
  -s ENVIRONMENT='web' \
  -s ALLOW_MEMORY_GROWTH=1

生成:

hello.js     ← 模块加载器(ES6 模块)
hello.wasm   ← WebAssembly 模块

📦 Step 3:在 Vue/Vite 中使用

hello-loader.js

import HelloModule from './hello.js'

export async function loadConcat() {
  const module = await HelloModule({
    locateFile: (path) => path === 'hello.wasm' ? '/hello.wasm' : path
  })

  const concat = module.cwrap('concat', 'number', ['string', 'string']);
  const free_str = module.cwrap('free_str', null, ['number']);

  // 包装函数,返回 JS 字符串并释放内存
  const concatStr = (a, b) => {
    const ptr = concat(a, b);
    const result = module.UTF8ToString(ptr);
    free_str(ptr);
    return result;
  }

  return concatStr;
}

App.vue 示例

<template>
  <div>
    <h2>拼接结果:{{ result }}</h2>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { loadConcat } from './wasm/hello-loader'

const result = ref('')

onMounted(async () => {
  const concat = await loadConcat()
  result.value = concat("Hello, ", "WebAssembly!")
})
</script>

🧪 输出

拼接结果:Hello, WebAssembly!

✅ 说明与注意事项

项目 说明
UTF8ToString 把 wasm 返回的char*指针转为 JS 字符串
stringToUTF8 JS 字符串传入 wasm 也可以用更复杂内存分配
free(ptr) 你可以自己控制是否释放(长生命周期可缓存)