Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EMSCRIPTEN_EXPORT option #4977

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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::
Expand All @@ -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:

Expand Down
1 change: 1 addition & 0 deletions system/include/emscripten/emscripten.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions tests/core/test_emscripten_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions tests/core/test_emscripten_api.out
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@ hello world!
*100*
*fivesix*
mann
keep-alive
em-export
0.123456789123121982165720567082 : 0.12345678912312198 : 0.123456789123121982165720567082 (19)
success
12 changes: 12 additions & 0 deletions tests/hello_function_export.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

#include <emscripten.h>
#include <math.h>

extern "C" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this into a .c file avoid this extern "C" block.


EMSCRIPTEN_EXPORT int int_sqrt(int x) {
return sqrt(x);
}

}

4 changes: 2 additions & 2 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -4012,12 +4012,12 @@ def test_emversion(self):

def test_dashE(self):
open('src.cpp', 'w').write(r'''#include <emscripten.h>
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'])

Expand Down