diff --git a/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst b/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst index 160ac96666b2..76595590e5c3 100644 --- a/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst +++ b/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst @@ -59,24 +59,22 @@ function and returns a JavaScript function you can call normally. :js:func:`cwrap` is therefore more useful if you plan to call a compiled function a number of times. -Consider the **tests/hello_function.cpp** file shown below. The +Consider the **tests/hello_function_export.cpp** file shown below. The ``int_sqrt()`` function to be compiled is wrapped in ``extern "C"`` to prevent C++ name mangling. -.. include:: ../../../../../tests/hello_function.cpp +.. include:: ../../../../../tests/hello_function_export.cpp :literal: +.. note:: + + `EMSCRIPTEN_EXPORT` (provided by the ``emscripten.h`` header) ensures that the + function isn't removed by optimization, and is exported so that it can be called from JS later. + To compile this code run the following command in the Emscripten home directory:: - ./emcc tests/hello_function.cpp -o function.html -s EXPORTED_FUNCTIONS="['_int_sqrt']" - -.. note:: - - `EXPORTED_FUNCTIONS` affects compilation to JavaScript. If you first compile to an object file, - then compile the object to JavaScript, you need that option on the second command. If you do - it all together as in the example here (source straight to JavaScript) then this just works, - of course. + ./emcc tests/hello_function_export.cpp -o function.html After compiling, you can call this function with :js:func:`cwrap` using the following JavaScript:: @@ -101,6 +99,17 @@ and enter the above commands as three separate commands, pressing ``5`` — the expected output for these inputs using C++ integer mathematics. +.. note:: + + We used `EMSCRIPTEN_EXPORT` in the source code of this example, as mentioned before, so that + the function isn't removed by optimization, and is exported so that it can be found by ``cwrap``. Another + option, instead of marking functions you want to export in the source code, is to add a commandline + flag to ``emcc``: by adding ``-s EXPORTED_FUNCTIONS="['_int_sqrt']"`` (note ``_`` prefix) we will export that function. Note that + `EXPORTED_FUNCTIONS` affects compilation to JavaScript, so if you first compile to an object file, + then compile the object to JavaScript, you need that option on the second command. (If you do + it all together as in the example here (source straight to JavaScript) then this just works, + of course.) + :js:func:`ccall` is similar, but receives another parameter with the parameters to pass to the function: diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index d1ab165fd508..242d0c87e689 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -55,6 +55,7 @@ typedef void (*em_str_callback_func)(const char *); #define EMSCRIPTEN_KEEPALIVE __attribute__((used)) +#define EMSCRIPTEN_EXPORT __attribute__((used)) extern void emscripten_run_script(const char *script); extern int emscripten_run_script_int(const char *script); diff --git a/tests/core/test_emscripten_api.cpp b/tests/core/test_emscripten_api.cpp index 6be7d87b74fc..61234ff39e43 100644 --- a/tests/core/test_emscripten_api.cpp +++ b/tests/core/test_emscripten_api.cpp @@ -4,6 +4,8 @@ extern "C" { void save_me_aimee() { printf("mann\n"); } +EMSCRIPTEN_KEEPALIVE void keep_alive() { printf("keep-alive\n"); } +EMSCRIPTEN_EXPORT void em_export() { printf("em-export\n"); } } int main() { @@ -12,6 +14,8 @@ int main() { printf("*%d*\n", emscripten_run_script_int("5*20")); printf("*%s*\n", emscripten_run_script_string("'five'+'six'")); emscripten_run_script("Module['_save_me_aimee']()"); + emscripten_run_script("Module['_keep_alive']()"); + emscripten_run_script("Module['_em_export']()"); // double d = 0.1234567891231219886553; int len = emscripten_print_double(d, NULL, -1); diff --git a/tests/core/test_emscripten_api.out b/tests/core/test_emscripten_api.out index c60188630847..1509b7a55b9a 100644 --- a/tests/core/test_emscripten_api.out +++ b/tests/core/test_emscripten_api.out @@ -2,5 +2,7 @@ hello world! *100* *fivesix* mann +keep-alive +em-export 0.123456789123121982165720567082 : 0.12345678912312198 : 0.123456789123121982165720567082 (19) success diff --git a/tests/hello_function_export.cpp b/tests/hello_function_export.cpp new file mode 100644 index 000000000000..9ea8edac9b07 --- /dev/null +++ b/tests/hello_function_export.cpp @@ -0,0 +1,12 @@ + +#include +#include + +extern "C" { + +EMSCRIPTEN_EXPORT int int_sqrt(int x) { + return sqrt(x); +} + +} + diff --git a/tests/test_other.py b/tests/test_other.py index 06a2a94db647..824c9f7c748a 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -4012,12 +4012,12 @@ def test_emversion(self): def test_dashE(self): open('src.cpp', 'w').write(r'''#include -EMSCRIPTEN_KEEPALIVE __EMSCRIPTEN_major__ __EMSCRIPTEN_minor__ __EMSCRIPTEN_tiny__ EMSCRIPTEN_KEEPALIVE +EMSCRIPTEN_KEEPALIVE __EMSCRIPTEN_major__ __EMSCRIPTEN_minor__ __EMSCRIPTEN_tiny__ EMSCRIPTEN_KEEPALIVE EMSCRIPTEN_EXPORT ''') def test(args=[]): print args out = Popen([PYTHON, EMCC, 'src.cpp', '-E'] + args, stdout=PIPE).communicate()[0] - self.assertContained(r'''__attribute__((used)) %d %d %d __attribute__((used))''' % (EMSCRIPTEN_VERSION_MAJOR, EMSCRIPTEN_VERSION_MINOR, EMSCRIPTEN_VERSION_TINY), out) + self.assertContained(r'''__attribute__((used)) %d %d %d __attribute__((used)) __attribute__((used))''' % (EMSCRIPTEN_VERSION_MAJOR, EMSCRIPTEN_VERSION_MINOR, EMSCRIPTEN_VERSION_TINY), out) test() test(['--bind'])