kunyoungparkk

Emscripten embind에서 동일한 JS 함수 이름으로 오버로딩하는 방법 본문

Web/WebAssembly

Emscripten embind에서 동일한 JS 함수 이름으로 오버로딩하는 방법

박건영 2025. 8. 30. 17:04

C++에서는 함수 오버로딩을 자유롭게 사용할 수 있습니다. 인자 개수나 타입에 따라 다른 함수를 같은 이름으로 정의할 수 있죠.

하지만 JavaScript는 기본적으로 함수 오버로딩을 지원하지 않습니다. JS 함수는 단 하나의 시그니처만 갖고, 호출 시 전달된 arguments를 해석하는 방식으로 구현자가 직접 분기해야 합니다.

 

그런데 Emscripten의 Embind를 이용해 C++ 코드를 WebAssembly로 바인딩하면, 놀랍게도 같은 이름의 함수를 오버로딩한 것처럼 JS API에서 쓸 수 있습니다.

이번 글에서는 Embind가 어떻게 이를 처리하는지 살펴보겠습니다.

 


select_overload 와 C++ 오버로딩

먼저, Emscripten에서 C++ 오버로딩을 JS에 노출하려면 select_overload를 사용해야 합니다.

 

그러나 현재 이 글에서 논의하는 것은, C++ 단의 오버로딩된 함수의 바인딩이 아니라,

JS단에서 호출하는 같은 이름의 함수를 바인딩하는 것이 가능하냐는 것입니다. 밑의 코드처럼 말이죠.

class MyClass {
public:
    void doSomething(int a, int b) {
        // ...
    
    }

    void doSomething(int a) {
        // ...
    }
};

EMSCRIPTEN_BINDINGS(my_bindings) {
    emscripten::class_<MyClass>("MyClass")
        .function("doSomething", emscripten::select_overload<bool(int, int)>(&MyClass::doSomething))
        .function("doSomething", emscripten::select_overload<bool(int)>(&MyClass::doSomething));
}

 

놀랍게도 이렇게 바인딩하면 JS 쪽에서는 하나의 함수이름으로 두 가지 호출 방식을 사용할 수 있습니다.

 


내부 동작: 오버로드 테이블과 디스패처 함수

 

그렇다면 JS는 오버로딩을 지원하지 않는데, 어떻게 이런 것이 가능할까요?

 

답은 Embind가 생성하는 디스패처 함수(dispatcher function)에 있습니다.

Embind는 같은 이름으로 여러 개의 오버로드가 등록되면, 내부적으로 overloadTable이라는 곳에 각각의 함수 구현을 저장합니다. 그리고 최종적으로 JS에 노출되는 것은 단일 함수인데, 이 함수가 호출될 때 arguments.length를 기준으로 어떤 구현을 실행할지 결정합니다.

밑 이미지는 emscripten/src/lib/libembind.js 파일 내용 중 일부입니다.

embind_register_function이 각각 바인딩된 함수를 처리하고, 최종적으로 replacePublicSymbol 내에서 overloadTable에 함수 구현을 저장하는 것을 확인할 수 있습니다.

 

 

즉, JS 문법 자체가 아니라 Embind 런타임이 “JS 오버로딩”을 에뮬레이션하는 방식입니다.