Where should I defined emscripten extern functions

2019-06-14 01:03发布

问题:

Suppose I have function x in C++ defined as:

extern "C" void x();

and I implement it in JS in global context

function _x() { console.log('x called'); }

_x is defined in asm compiled js file, which is getting invoked and not my implementation. What am I doing wrong?

I'm getting this warning while linking:

warning: unresolved symbol: x

Here is the stacktrace:

Uncaught abort() at Error
at jsStackTrace (http://localhost/module.js:978:13)
at stackTrace (http://localhost/module.js:995:22)
at abort (http://localhost/module.js:71106:25)
at _x (http://localhost/module.js:5829:46)
at Array._x__wrapper (http://localhost/module.js:68595:41)
at Object.dynCall_vi (http://localhost/module.js:68442:36)
at invoke_vi (http://localhost/module.js:7017:25)
at _LoadFile (http://localhost/module.js:7573:6)
at asm._LoadFile (http://localhost/module.js:69219:25)
at eval (eval at cwrap (http://localhost/module.js:554:17), <anonymous>:6:26)

回答1:

As described at Implement a C API in Javascript, you define a library by having a Javascript file that calls mergeInto to merge an object with your Javascript functions into LibraryManager.library. You then compile with the --js-library option to pass in the location of your library.

For example, you can have Javascript file with your library of a single function

// In library.js
mergeInto(LibraryManager.library, {
  x: function() {
    alert('hi');
  },
});

a main C++ file that calls this function

// in librarytest.cc
extern "C" void x();

int main()
{
  x();
  return 0;
}

and compile to HTML and Javascript with

em++ librarytest.cc --js-library library.js -o librarytest.html

then you load librarytest.html in a browser, it will show an alert box with hi.



回答2:

If you want to pass a string from C++ to Javascript, you don't have to go the route of Implement a C API in Javascript. Instead, you can use the EM_ASM* macros to directly inline the Javascript. This can then call out to Javascript functions you have defined, and pass their values.

Also, to pass a string, you need to make sure you pass a C-style string, and then use the Emscripten-supplied Pointer_stringify Javascript function on the result:

#include <string>

#include <emscripten.h>

int main()
{
  std::string myString("This is a string in C++");

  EM_ASM_ARGS({
    console.log(Pointer_stringify($0));
  }, myString.c_str());

  return 0;
}