Last active
May 28, 2020 21:15
-
-
Save igormcoelho/5d7e1ba721c0f1e4ec9eec07b6c97d41 to your computer and use it in GitHub Desktop.
Bundle (webkit) C++ on emscripten (1.39.4) with external node.js dependency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
docker run --rm -v $(pwd):/src trzeci/emscripten em++ --pre-js prefix-node-require.js --std=c++17 -g -O3 -Wall -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap", "UTF8ToString", "stringToUTF8"]' -s DISABLE_EXCEPTION_CATCHING=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME="ourtest"' --js-library general-exports.js -I./thirdparty/my-cpp-library/ -o ourtest.js mycode.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mergeInto( | |
LibraryManager.library, { | |
// 'strInput' is a null terminated char array | |
// 'ptr_out' is a 'unsigned char*' array of size 'sz_out' (it's pre-allocated by its user in C) | |
external_sha256: function (strInput, ptr_out, sz_out) { | |
// gets external js library | |
let myCryptoJS = Module['CryptoJS']; | |
// converts 'char*' to 'js string' | |
var hexv1 = Module.UTF8ToString(strInput); | |
// invokes external library | |
var hexEnc1 = myCryptoJS.enc.Hex.parse(hexv1); | |
// use external desired function (SHA256) | |
var outEnc1 = myCryptoJS.SHA256(hexEnc1); | |
// prepares output to put on 'byte*' array | |
var hex_out = myCryptoJS.enc.Hex.stringify(outEnc1); | |
const fromHexString = hexString => | |
new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); | |
var vout = fromHexString(hex_out); | |
// copy output into C memory | |
Module.HEAPU8.set(vout, ptr_out); // could check 'sz_out' for better safety | |
// returns used length | |
return vout.length; | |
} | |
} | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<script src="./dist/bundle.js"></script> | |
<script> | |
myLib.myOnInit( | |
function () { | |
console.log(myLib.add_10(50)); // result is 60 | |
} | |
); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ourtest from './ourtest.js'; | |
import ourtestWasm from './ourtest.wasm'; | |
// 'index.html' could access 'myLib.mymodule' | |
export const mymodule = ourtest({ | |
locateFile(path) { | |
if(path.endsWith('.wasm')) { | |
return ourtestWasm; | |
} | |
return path; | |
} | |
}); | |
// 'index.html' could access 'myLib.myadd_10' | |
export const myadd_10 = mymodule._add_10; | |
// 'index.html' could access 'myLib.c_myfunction' | |
export const c_myfunction = mymodule.cwrap('c_myfunction', 'string', ['string']); | |
// initialization callback | |
let myFunc = function(){console.log("initialized wasm");}; | |
export function myOnInit(f){ | |
myFunc = f; | |
}; | |
mymodule.onRuntimeInitialized = () => { | |
console.log(mymodule._add_10(20)); // outputs 30 | |
myFunc(); | |
}; | |
// 'index.html' could access 'myLib.CryptoJS' | |
export const CryptoJS = require('crypto-js'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <my-cpp-project/cpp-bindings.hpp> | |
// C++ function: std::string myCppFunction(std::string s) { /* c++ implementation */ } | |
// C function (for JS): extern "C" int external_sha256(const char* input_hexstring, unsigned char* output_bytes, int sz_output); | |
EMSCRIPTEN_KEEPALIVE | |
extern "C" | |
const char* c_myfunction(const char* cs_in) { | |
std::string sin(cs_in); | |
std::string s_out = myCppFunction(sin); | |
return s_out.c_str(); // is it really safe? | |
} | |
#include <emscripten.h> | |
EMSCRIPTEN_KEEPALIVE | |
extern "C" | |
int add_10(int n) { | |
return n+10; | |
} | |
int | |
main() | |
{ | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "lol", | |
"scripts": { | |
"build:codec": "./compile.sh", | |
"build:bundle": "webpack", | |
"build": "npm run build:codec && npm run build:bundle", | |
"serve": "http-server", | |
"start": "npm run build && npm run serve" | |
}, | |
"devDependencies": { | |
"exports-loader": "^0.7.0", | |
"file-loader": "^1.1.11", | |
"http-server": "^0.11.1", | |
"webpack": "^4.8.2", | |
"webpack-cli": "^3.1.2" | |
}, | |
"dependencies": { | |
"crypto-js": "", | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is only valid for node.js (but after bundle process, it will be usable on web too) | |
let lt_cryptojs = require('crypto-js'); | |
Module["CryptoJS"] = lt_cryptojs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on: https://gist.github.com/surma/b2705b6cca29357ebea1c9e6e15684cc | |
const webpack = require("webpack"); | |
const path = require("path"); | |
module.exports = { | |
mode: "development", | |
context: path.resolve(__dirname, "."), | |
entry: "./index.js", | |
output: { | |
path: path.resolve(__dirname, "dist"), | |
filename: "bundle.js", | |
library: 'myLib', | |
libraryTarget: 'umd' | |
}, | |
node: { | |
fs: "empty" | |
}, | |
module: { | |
rules: [ | |
{ | |
test: /ourtest\.js$/, | |
loader: "exports-loader" | |
}, | |
{ | |
test: /ourtest\.wasm$/, | |
type: "javascript/auto", | |
loader: "file-loader", | |
options: { | |
publicPath: "dist/" | |
} | |
} | |
] | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice example, brother! This may be useful to someone else and save a couple of hours.
Can you remove the
,
from:File
#include <my-cpp-project/cpp-bindings.hpp>
is missing.