🕌

WASM Emscripten/Embind で int64_t が unknown type x になる

2022/02/08に公開

JavaScript の Number型は 一般的にfloat64 型のため、int64/uint64型 をJavaScript側に公開すると 例外が送出される。

解決策

int64/uint64の暗黙の型変換を行わないので、公開側で明示的にdoubleに型変換を行う。

なお、double の仮数部は 52bit なので、整数として扱える最大値は 45035996273704950xfffff'ffffffff)であることに注意する必要がある。

具体例

WASM側で Array.push() を呼び出した場合

WASM側

emscripten::val get_array() {
    auto val = emscripten::val::array();
    int64_t answer = 42;
    val.call<emscripten::val>("push", answer);
    return val;
}

EMSCRIPTEN_BINDINGS(my_module) {
    function("get_array", &get_array);
}
$ my_module.get_array()
BindingError: parameter 1 has unknown type x

解決策

emscripten::val get_array() {
    auto val = emscripten::val::array();
    int64_t answer = 42;
    val.call<emscripten::val>("push", static_cast<double>(answer));
    return val;
}
$ my_module.get_array()
[42]

公開関数の引数に int64_t を定義し、JavaScript側から呼び出した場合

WASM側

std::int64_t func(std::int64_t x) {
    return x + 42;
}

EMSCRIPTEN_BINDINGS(my_module) {
    function("func", &func);
}
$ my_module.func(0)
UnboundTypeError: Cannot call func due to unbound types: x

解決策

std::int64_t func(std::int64_t x) {
    return x + 42;
}

EMSCRIPTEN_BINDINGS(my_module) {
    function("func", optional_override([](double x) -> double {
	return func(x);
    }));
}
$ my_module.func(0)
42

参考文献

Discussion