twiddlingbits / twr-wasm

twr-wasm: easily run C/C++ code in a web browser using Web Assembly, with examples
https://twiddlingbits.dev/
MIT License
19 stars 2 forks source link

Template/Generic Compilation #51

Closed JohnDog3112 closed 1 month ago

JohnDog3112 commented 1 month ago

I mentioned this over the phone, however, I found a temporary solution and would like some input on why it was necessary.

The problem stems from a generic LinkedList implementation I made:

template<typename T>
class LinkedListRoot {
   public:
   LinkedList<T>* root = NULL;
   LinkedListRoot();
   ~LinkedListRoot();
   void addNode(T val);

   private:
   LinkedList<T>* tail = NULL;
};

When this was implemented in pong-menu.h and pong-menu.cpp (where it was used), everything worked fine. However, when I was setting up a new class for rendering centered text I moved it to extra.h and extra.cpp so it could be used among multiple files. When I did this, I started getting the following linking errors:

wasm-ld: error: out/pong-menu.o: undefined symbol: LinkedListRoot<MenuButton>::LinkedListRoot()
wasm-ld: error: out/pong-menu.o: undefined symbol: LinkedListRoot<MenuButton>::addNode(MenuButton)
wasm-ld: error: out/pong-menu.o: undefined symbol: LinkedListRoot<MenuButton>::addNode(MenuButton)
wasm-ld: error: out/pong-menu.o: undefined symbol: LinkedListRoot<MenuButton>::addNode(MenuButton)
wasm-ld: error: out/entry-point.o: undefined symbol: LinkedListRoot<MenuButton>::~LinkedListRoot()

I found that moving the MenuButton struct into extra.h and adding:

template class LinkedListRoot<MenuButton>;

to extra.cpp fixed it.

I was wondering if you knew what might be causing the explicit declaration to be necessary and if there's any other way I could fix this?

JohnDog3112 commented 1 month ago

I figured out that putting all of the function definitions in the header fixed the issue. I'm still not quite sure why it's necessary, but it's a better solution than needing to define every variant of the class in extra.cpp.

twiddlingbits commented 1 month ago

I had answered this in a different issue. https://github.com/twiddlingbits/twr-wasm/issues/14. Here is what I found:

However, I keep getting linking issues with it. Do you know what might be causing these?

chatGPT says: https://chatgpt.com/share/66f9d97d-481c-800a-9372-c31f27465483

Here is what I wrote before I aske chatGPT, but I haven't really used templates in c++ (i do use them in typescript):

If you show me the code (commit it, or provide a link, or whatever), i can take a look. But I will say that in the past whenever I have tried to put actual code in a .h file it has never ended well and I always end up putting it in a .cpp file (and the class detentions in a .h file, like canvas.cpp). When it's in the .h, then you end up with name collision (same name compiled into multiple .o). I think you can work around it with appropriate use of inline, but that seems to be very fragile and confusing. I gave up getting it to work the one time i tried recently. You could make the code static, which might avoid the collision. But then you still have multiple copies of the same code, which doesn't seem clean, and there are probably other issues.

twiddlingbits commented 1 month ago

i sent you an email with an intro to don, who can explain this in detail.

twiddlingbits commented 1 month ago

please close this if you think its fixed.