0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Windows11 の VSCode+Emscripten で wasm によるハローワールド (4)

Last updated at Posted at 2025-10-09

すべての記事

JavaScript から C++ の関数を呼び出す

C++ の関数呼び出しについては、検索すると参考になる記事も多くここで特筆すべき内容も特にないので、ファイルのみ掲載している。

C:\wasm\project\03-call-cpp-func\.vscode\launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "localhost:8080",
            "url": "http://localhost:8080/",
        }
    ]
}

C:\wasm\project\03-call-cpp-func\CMakePresets.json

{
  "version": 5,
  "cmakeMinimumRequired": {
    "major": 3,
    "minor": 20,
    "patch": 0
  },
  "configurePresets": [
    {
      "name": "wasm-config-debug",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build",
      "cacheVariables": {
        "CMAKE_CXX_STANDARD": "17",
        "CMAKE_CXX_STANDARD_REQUIRED": "ON",
        "CMAKE_CXX_EXTENSIONS": "OFF",
        "CMAKE_TOOLCHAIN_FILE": "$env{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
        "CMAKE_BUILD_TYPE": "Debug"
      }
    }
  ],
  "buildPresets": [
    {
      "name": "wasm-build-debug",
      "configurePreset": "wasm-config-debug",
      "verbose": true
    }
  ]
}

C:\wasm\project\03-call-cpp-func\CMakeLists.txt
C++ のソースコードに main() が無いので、--no-entry としている。

cmake_minimum_required(VERSION 3.20)
project(03_call_cpp_func LANGUAGES CXX)

add_executable(03_call_cpp_func func.cpp)
target_link_options(03_call_cpp_func PRIVATE
    "-gsource-map"
    "-sASSERTIONS=1"
    "-sSAFE_HEAP=1"
    "--no-entry"
    "-sEXPORTED_FUNCTIONS=_malloc,_free"
    "-sEXPORTED_RUNTIME_METHODS=wasmExports,ccall,stringToUTF8OnStack,UTF8ToString,HEAP32"
)

C:\wasm\project\03-call-cpp-func\index.html

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8"/>
        <script src="build/03_call_cpp_func.js"></script>
        <script>
            const cpp_func_example = () =>
            {
                let v = 0;
                let s = '';

                // 数値を扱う関数: ccall による呼び出し
                v = Module.ccall('increment', 'number', ['number'], [v]);
                console.log(`return=${v}`);

                // 数値を扱う関数: wasmExports を利用した呼び出し
                v = Module.wasmExports.increment(v);
                console.log(`return=${v}`);

                // 数値を扱う関数: 直接呼出し
                v = Module._increment(v);
                console.log(`return=${v}`);

                // 文字列を扱う関数: ccall による呼び出し
                v = Module.ccall('str_repeat', 'number', ['string', 'number'], ['HELLO1 ', 3]);
                s = Module.UTF8ToString(v);
                Module._free(v);
                console.log(`return=${s}`);

                // 文字列を扱う関数: wasmExports を利用した呼び出し
                v = Module.stringToUTF8OnStack('HELLO2 ');
                v = Module.wasmExports.str_repeat(v, 3);
                s = Module.UTF8ToString(v);
                Module._free(v);
                console.log(`return=${s}`);

                // 数値配列を扱う関数
                const js_nums = Array.from({ length: 10 }, (_, i) => i + 1);
                const intptr = Module._malloc(js_nums.length * Module.HEAP32.BYTES_PER_ELEMENT);
                Module.HEAP32.set(js_nums, intptr / Module.HEAP32.BYTES_PER_ELEMENT);
                v = Module.wasmExports.sum(intptr, js_nums.length);
                console.log(`return=${v}`);
                Module._free(intptr);
            };

            Module.onRuntimeInitialized = () =>
            {
                cpp_func_example();
            };
        </script>
    </head>
    <body>
    </body>
</html>

C:\wasm\project\03-call-cpp-func\func.cpp

// UTF-8N CRLF
#include <emscripten.h>
#include <cstdio>
#include <cstring>
#include <numeric>

extern "C"
EMSCRIPTEN_KEEPALIVE
int increment(int v)
{
	printf("-- increment(%d)\n", v);
	return v + 1;
}

extern "C"
EMSCRIPTEN_KEEPALIVE
char* str_repeat(const char* str, int num)
{
	printf("-- str_repeat(%s, %d)\n", str, num);
	char* ret = (char*)malloc(strlen(str) * num + 1);
	ret[0] = '\0';

	for (int i=0; i<num; ++i) {
		strcat(ret, str);
	}

	return ret;
}

extern "C"
EMSCRIPTEN_KEEPALIVE
int sum(const int* nums, int len)
{
	printf("-- sum(%d..%d)\n", nums[0], nums[len - 1]);
	return std::accumulate(nums, nums + len, 0);
}

// EOF

実行結果

前の例 と同じようにデバッグを実行するとコンソールには以下のような表示が行われる

-- increment(0)
return=1
-- increment(1)
return=2
-- increment(2)
return=3
-- str_repeat(HELLO1 , 3)
return=HELLO1 HELLO1 HELLO1
-- str_repeat(HELLO2 , 3)
return=HELLO2 HELLO2 HELLO2
-- sum(1..10)
return=55

次回 は静的ライブラリを作成する。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?