Unable to Export C++ Classes from a Main Module to a Side Module

230 views
Skip to first unread message

awt

unread,
Jul 13, 2018, 1:27:51 PM7/13/18
to emscripten-discuss
Hi,

I have a C++ class that's defined in a main module that I want to export to a side module but I'm not able to get it working. Somehow, the mangled name for the default constructor is different in the main and side module. 

This is how I declare the class:

class EMSCRIPTEN_KEEPALIVE GlobalConstructor {
public:
  
  GlobalConstructor();
  GlobalConstructor(int i);

  int testExport(int i);
  int* tmp;
};

These are the definitions:
 GlobalConstructor::GlobalConstructor() {
    tmp = new int(11);
  }


  GlobalConstructor::GlobalConstructor(int i) {
    tmp = new int(i);
  }

  int GlobalConstructor::testExport(int i) {
    return i + 7;
  }


This is how I use it in the side module:

GlobalConstructor test(11);
printf("main+ tmp:%d %d\n", *(test.tmp), test.testExport(9));

Unfortunately, the default constructor in the main module is defined as __ZN17GlobalConstructorC2Ei while the side module is trying to import __ZN17GlobalConstructorC1Ei. Does anybody know what's going wrong here and what can we do to resolve this? Thanks.

Alon Zakai

unread,
Jul 16, 2018, 12:38:43 PM7/16/18
to emscripten-discuss
The difference in the 2 names is because one is an alias of the other, I believe. I thought we handled aliases properly in dynamic linking, though - we even have test_dylink_class (in tests/test_core.py) which should cover that.

To debug this, I'd start by seeing that the test passes for you (./tests/runner.py test_dylink_class). Then I'd modify the test to be more like your code that fails, and see what change causes the failure. The difference should point us to what is wrong.



--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

awt

unread,
Jul 17, 2018, 5:47:39 PM7/17/18
to emscripten-discuss
Thanks for your reply Alon. After some debugging, I found that the test suite was exporting a class from the side module to the main module and the aliasing is done correctly. However, I don’t see any aliasing when we export a class from the main to the side module. 

This is what I see when we export a class side from the side to main module:
(export "__ZN4sideC1Ei" (func $__ZN4sideC2Ei))
(export "fp$__ZN4sideC2Ei" (global $global$2))


This is what I see when we export a class GlobalConstructor from the main to the side module:
(export "__ZN17GlobalConstructorC2Ei" (func $__ZN17GlobalConstructorC2Ei))

I didn't see any aliasing when I export a class from the Main module in this case. Is this a bug? and if it is, can you direct me to the code that creates the aliasing?. Thanks.

Alon Zakai

unread,
Jul 17, 2018, 8:36:39 PM7/17/18
to emscripten-discuss
Hmm, test_dylink_class should test exporting from the main to the side and vice versa, so we should have coverage of that case. When you run it, it will print "flip" when it reverses them.

I believe the relevant code is the stuff using  metadata['aliases']  in emscripten.py.

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

awt

unread,
Jul 19, 2018, 12:14:03 AM7/19/18
to emscripten-discuss
You are right Alon, the test does filp the exporting of the struct. After some more debugging, I realized that the faliure can be reproduced with MAIN_MODULE=2 instead of MAIN_MODULE=1 in the following line:


The exported code is no longer aliased when we use MAIN_MODULE=2. Do you have any indication of what might have possibly gone wrong here? Thanks.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alon Zakai

unread,
Jul 19, 2018, 3:40:34 PM7/19/18
to emscripten-discuss
Interesting, I think you're close to finding the bug. So in mode 2 we do dce - we just keep alive things that are exported. I suspect we need to also keep alive aliases in that case, and maybe the bug is that we currently don't. (That is, in emscripten.py when we know the aliases, we can add exporting of aliases for each exported function.)

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

awt

unread,
Jul 21, 2018, 1:49:35 PM7/21/18
to emscripten-discuss
Alon, 

I realized that with MAIN_MODULE=2, the metadata generated by parse_backend_output at https://github.com/kripken/emscripten/blob/92f8a3366056a975cda059b82eaa2cabd6c3b2c7/emscripten.py#L95
already do not contain the aliases. 

Does this mean that the aliases were already removed in fastcomp and not emscripten.py? Can you give me some direction on where aliases might possibly be removed in fastcomp for MAIN_MODULE=2 as opposed to MAIN_MODULE=1? Thanks.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alon Zakai

unread,
Jul 22, 2018, 9:04:26 PM7/22/18
to emscripten-discuss
Hmm, it's possible that when LLVM does dce (globalopt, specifically), which we tell it to in MAIN_MODULE mode 2, then it removes unused aliases. That makes sense actually.

In that case, the only option would be to either not do dce (mode 1, that is, normal linking where we assume other code we link in later might need anything), or for the user to add the class constructors *and their aliases* to the list of EXPORTED_FUNCTIONS, which LLVM will keep alive.

The only improvement I can see is to let the user only specify the constructors, and we'd add their aliases based on them, perhaps. Maybe that could be done in python somewhere, basically just scan the list of EXPORTED_FUNCTIONS and see if they are constructors. But not sure it's worthwhile.



To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

awt

unread,
Jul 23, 2018, 11:34:55 AM7/23/18
to emscripten-discuss
By the way, I saw this error when trying to apply EMSCRIPTEN_KEEPALIVE to a class:

d:\git\dylink_demandload/GlobalConstructor.h:9:8: warning: 'used' attribute only applies to variables and functions
      [-Wignored-attributes]
struct EMSCRIPTEN_KEEPALIVE GlobalConstructor {
       ^
D:\Packages\emsdk_win\1.37.36\emscripten\1.37.36\system\include/emscripten/emscripten.h:58:45: note: expanded from macro
      'EMSCRIPTEN_KEEPALIVE'
#define EMSCRIPTEN_KEEPALIVE __attribute__((used))

It seems that LLVM will only allow us to export variables and functions but not classes? I tried using __attribute__ ((visibility ("default"))) but my class members were not exported as well. Do you know of any other macros or attributes that we can use to export a class? If not, I will just add EMSCRIPTEN_KEEPALIVE to all class methods that need to be exported then. Thanks.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alon Zakai

unread,
Jul 23, 2018, 4:55:04 PM7/23/18
to emscripten-discuss
I don't know much about this, but yeah, based on that error, attributes apply only to functions so you'd need to apply it to each method of a class you want to export. (Or, add them to EXPORTED_FUNCTIONS, but that's perhaps no more convenient.)

Perhaps we could add an option "EXPORTED_CLASSES" that gets class names and then uses name demangling to export all functions belonging to a class. Not sure offhand how easy that would be.


To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages