
C 언어를 컴파일 후 직접 실행 해보고, emsdk를 이용하여 wasm으로 컴파일 한 후 브라우저에서 사용하는 내용을 담았습니다.
shuffle.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(int arr[], int n) {
srand(time(NULL));
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int main(int argc, char *argv[]) {
int n = argc - 1; // 명령행 인수의 개수를 배열의 길이로 사용
int arr[n]; // 배열 생성
// 명령행 인수를 배열로 변환
for (int i = 0; i < n; i++) {
arr[i] = atoi(argv[i + 1]);
}
shuffle(arr, n);
printf("Shuffled array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
gcc -o shuffle shuffle.c
./shuffle 1 2 3 4 5
#output 2 4 5 3 1
💡 Emscripten는 웹 플랫폼에 중점을 둔 WASM 컴파일러 툴 체인이다.
💡 SDK는 특정한 소프트웨어를 개발하기 위해 필요한 도구, 라이브러리, 문서 등을 모아놓은 패키지를 뜻한다.
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
git pull
# 최신 버전 다운받기
./emsdk install latest
# 최신 버전 활성화
./emsdk activate latest
# 환경변수 설정
source ./emsdk_env.sh
💡 ./emsdk activate latest를 입력하면 아래와 같은 결과를 받을 수 있다.
ehco 부분을 그대로 복붙하면 어느 경로에서든 터미널로 Emscripten SDK에 접근할 수 있다.
emsdk list
hello.c
#include <stdio.h>
#include <emscripten/emscripten.h>
int main() {
return 0;
}
EMSCRIPTEN_KEEPALIVE int throw_number(int argc, char ** argv) {
return 777;
}
이를 해결하기 위해 which emcc로 c 언어를 컴파일 해줄 emscripten 컴파일러의 위치를 찾자
c_cpp_properties.json 파일에 includePath에 추가하기{
"configurations": [
{
// ...
"includePath": [
"${workspaceFolder}/**",
"/Users/jeong-youseock/Desktop/emsdk/upstream/emscripten/**" 👈
]
}
]
}emcc --no-entry ./throw_number.c -o ./throw_number.wasm \
-O3 \
-s ENVIRONMENT='web' \
-s EXPORTED_FUNCTIONS='["_throw_number","_malloc","_free"]'
하나씩 살펴보자
WebAssembly 객체는 Wasm과 관련된 모든 기능에 대한 네임스페이스 역할을 한다. 즉, Wasm 모듈과 상호작용하고 제어하는 데 사용되는 메서드와 속성을 제공하며, WebAssembly 객체를 사용하여 Wasm 모듈을 로드하고 실행하며, Wasm 모듈을 호출하고 결과를 처리할 수 있다.
💡 네임스페이스 역할을 한다는 것은 무엇을 의미할까?
일반적인 내장 객체는 생성자 역할을 하지만 그렇지 않은 내장 객체들도 있다.
WebAssembly도 Intl, Math와 같이 비슷한 역할을 하는 메소드들의 패키지이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<script>
document.addEventListener("DOMContentLoaded", () => {
const button = document.querySelector("button");
const span = document.querySelector("span");
button.addEventListener("click", () => {
WebAssembly.instantiateStreaming(fetch("./throw_number.wasm"))
.then((result) => {
const { throw_number } = result.instance.exports;
span.textContent = throw_number();
})
.catch(console.error);
});
});
</script>
<body>
<button>어셈블 불러보기</button>
<span></span>
</body>
</html>
