Reputation: 63
I have been trying to use this library in my C++ project for some time now and can't seem to figure out how to get around the issue of multiple definitions. The library contains only header files (and implementation header files) so the source folder looks like this:
├── src
│ ├── SomeHeaderFile.h
│ ├── SomeHeaderFile-Impl.h
│ ├── SomeOtherHeaderFile.h
│ ├── SomeOtherHeaderFile-Impl.h
│ ├── ...
├── ...
I have no issues using the library in my main .cpp file, but when I also try to include it in another .cpp file I get multiple definition errors.
There are definitions in the header files so I understand why #pragma and #ifndef guards don't protect the function/classes declarations. The library is also big enough that I can't justify going into the code and adding inline to all declarations, let alone dumping the declarations into a .cpp file. These are the main pointers/suggestions that I have ran into while trying to learn how to use this library. So is there a correct way to use this library without having to modify it?
EDIT: Adding a picture of my minimal reproducible example. This is just a snippet of the error/warning message, there are multiple definition errors for pretty much every definition in the library:
EDIT 2: Adding code for MRE:
The project structure is the following (using PlatformIO on VSCode):
├── .pio
│ ├── build
│ ├── libdeps
│ │ ├── WebSockets_Generic
│ │ ├──...
├── include
│ ├── other_file.h
├── lib
│ ├── TestLib
│ │ ├── TestLib.h
├── src
│ ├── main.cpp
│ ├── other_file.cpp
Inside main.cpp
:
#include <Arduino.h>
#include <TestLib.h>
void setup() {}
void loop() {}
Inside other_file.cpp
:
#include <other_file.h>
Inside other_file.h
:
#ifndef OTHER_FILE_H
#define OTHER_FILE_H
#include <TestLib.h>
#endif
Inside TestLib.h
:
#pragma once
#ifndef TESTLIB_H
#define TESTLIB_H
#define WEBSOCKETS_NETWORK_TYPE NETWORK_QN_ETHERNET //NETWORK_NATIVEETHERNET
#define _WEBSOCKETS_LOGLEVEL_ 1
#include <WebSockets_Generic.h>
#endif
You would need to install the library through the PlatformIO manager, but the full compilation error is the following:
Linking .pio\build\teensy41\firmware.elf
.pio\build\teensy41\src\other_file.cpp.o: In function `WS_IPAddressToString(IPAddress const&)':
other_file.cpp:(.text._Z20WS_IPAddressToStringRK9IPAddress+0x0): multiple definition of `WS_IPAddressToString(IPAddress const&)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._Z20WS_IPAddressToStringRK9IPAddress+0x0): first defined here
c:/users/user/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
.pio\build\teensy41\src\other_file.cpp.o: In function `base64_init_encodestate':
other_file.cpp:(.text.base64_init_encodestate+0x0): multiple definition of `base64_init_encodestate'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text.base64_init_encodestate+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `base64_init_encodestate_nonewlines':
other_file.cpp:(.text.base64_init_encodestate_nonewlines+0x0): multiple definition of `base64_init_encodestate_nonewlines'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text.base64_init_encodestate_nonewlines+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `base64_encode_value':
other_file.cpp:(.text.base64_encode_value+0x0): multiple definition of `base64_encode_value'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text.base64_encode_value+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `base64_encode_block':
other_file.cpp:(.text.base64_encode_block+0x0): multiple definition of `base64_encode_block'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text.base64_encode_block+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `base64_encode_blockend':
other_file.cpp:(.text.base64_encode_blockend+0x0): multiple definition of `base64_encode_blockend'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text.base64_encode_blockend+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `base64_encode_chars':
other_file.cpp:(.text.base64_encode_chars+0x0): multiple definition of `base64_encode_chars'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text.base64_encode_chars+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::createHeader(unsigned char*, WSopcode_t, unsigned int, bool, unsigned char*, bool)':
other_file.cpp:(.text._ZN10WebSockets12createHeaderEPh10WSopcode_tjbS0_b+0x0): multiple definition of `WebSockets::createHeader(unsigned char*, WSopcode_t, unsigned int, bool, unsigned char*, bool)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets12createHeaderEPh10WSopcode_tjbS0_b+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::sendFrameHeader(WSclient_t*, WSopcode_t, unsigned int, bool)':
other_file.cpp:(.text._ZN10WebSockets15sendFrameHeaderEP10WSclient_t10WSopcode_tjb+0x0): multiple definition of `WebSockets::sendFrameHeader(WSclient_t*, WSopcode_t, unsigned int, bool)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets15sendFrameHeaderEP10WSclient_t10WSopcode_tjb+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::headerDone(WSclient_t*)':
other_file.cpp:(.text._ZN10WebSockets10headerDoneEP10WSclient_t+0x0): multiple definition of `WebSockets::headerDone(WSclient_t*)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets10headerDoneEP10WSclient_t+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::base64_encode(unsigned char*, unsigned int)':
other_file.cpp:(.text._ZN10WebSockets13base64_encodeEPhj+0x0): multiple definition of `WebSockets::base64_encode(unsigned char*, unsigned int)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets13base64_encodeEPhj+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::acceptKey(String&)':
other_file.cpp:(.text._ZN10WebSockets9acceptKeyER6String+0x0): multiple definition of `WebSockets::acceptKey(String&)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets9acceptKeyER6String+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::write(WSclient_t*, char const*)':
other_file.cpp:(.text._ZN10WebSockets5writeEP10WSclient_tPKc+0x0): multiple definition of `WebSockets::write(WSclient_t*, char const*)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets5writeEP10WSclient_tPKc+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::enableHeartbeat(WSclient_t*, unsigned long const&, unsigned long const&, unsigned char const&)':
other_file.cpp:(.text._ZN10WebSockets15enableHeartbeatEP10WSclient_tRKmS3_RKh+0x0): multiple definition of `WebSockets::enableHeartbeat(WSclient_t*, unsigned long const&, unsigned long const&, unsigned char const&)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets15enableHeartbeatEP10WSclient_tRKmS3_RKh+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::handleHBTimeout(WSclient_t*)':
other_file.cpp:(.text._ZN10WebSockets15handleHBTimeoutEP10WSclient_t+0x0): multiple definition of `WebSockets::handleHBTimeout(WSclient_t*)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets15handleHBTimeoutEP10WSclient_t+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::sendFrame(WSclient_t*, WSopcode_t, unsigned char*, unsigned int, bool, bool)':
other_file.cpp:(.text._ZN10WebSockets9sendFrameEP10WSclient_t10WSopcode_tPhjbb+0x0): multiple definition of `WebSockets::sendFrame(WSclient_t*, WSopcode_t, unsigned char*, unsigned int, bool, bool)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets9sendFrameEP10WSclient_t10WSopcode_tPhjbb+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::clientDisconnect(WSclient_t*, unsigned short, char*, unsigned int)':
other_file.cpp:(.text._ZN10WebSockets16clientDisconnectEP10WSclient_ttPcj+0x0): multiple definition of `WebSockets::clientDisconnect(WSclient_t*, unsigned short, char*, unsigned int)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets16clientDisconnectEP10WSclient_ttPcj+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::handleWebsocketPayloadCb(WSclient_t*, bool, unsigned char*)':
other_file.cpp:(.text._ZN10WebSockets24handleWebsocketPayloadCbEP10WSclient_tbPh+0x0): multiple definition of `WebSockets::handleWebsocketPayloadCb(WSclient_t*, bool, unsigned char*)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets24handleWebsocketPayloadCbEP10WSclient_tbPh+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::write(WSclient_t*, unsigned char*, unsigned int)':
other_file.cpp:(.text._ZN10WebSockets5writeEP10WSclient_tPhj+0x0): multiple definition of `WebSockets::write(WSclient_t*, unsigned char*, unsigned int)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets5writeEP10WSclient_tPhj+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::readCb(WSclient_t*, unsigned char*, unsigned int, std::function<void (WSclient_t*, bool)>)':
other_file.cpp:(.text._ZN10WebSockets6readCbEP10WSclient_tPhjSt8functionIFvS1_bEE+0x0): multiple definition of `WebSockets::readCb(WSclient_t*, unsigned char*, unsigned int, std::function<void (WSclient_t*, bool)>)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets6readCbEP10WSclient_tPhjSt8functionIFvS1_bEE+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::handleWebsocketWaitFor(WSclient_t*, unsigned int)':
other_file.cpp:(.text._ZN10WebSockets22handleWebsocketWaitForEP10WSclient_tj+0x0): multiple definition of `WebSockets::handleWebsocketWaitFor(WSclient_t*, unsigned int)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets22handleWebsocketWaitForEP10WSclient_tj+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::handleWebsocketCb(WSclient_t*)':
other_file.cpp:(.text._ZN10WebSockets17handleWebsocketCbEP10WSclient_t+0x0): multiple definition of `WebSockets::handleWebsocketCb(WSclient_t*)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets17handleWebsocketCbEP10WSclient_t+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o: In function `WebSockets::handleWebsocket(WSclient_t*)':
other_file.cpp:(.text._ZN10WebSockets15handleWebsocketEP10WSclient_t+0x0): multiple definition of `WebSockets::handleWebsocket(WSclient_t*)'
.pio\build\teensy41\src\main.cpp.o:main.cpp:(.text._ZN10WebSockets15handleWebsocketEP10WSclient_t+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o:(.rodata._ZTV10WebSockets+0x0): multiple definition of `vtable for WebSockets'
.pio\build\teensy41\src\main.cpp.o:(.rodata._ZTV10WebSockets+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o:(.bss._ZSt11__exidx_end+0x0): multiple definition of `std::__exidx_end'
.pio\build\teensy41\src\main.cpp.o:(.bss._ZSt11__exidx_end+0x0): first defined here
.pio\build\teensy41\src\other_file.cpp.o:(.bss._ZSt13__exidx_start+0x0): multiple definition of `std::__exidx_start'
.pio\build\teensy41\src\main.cpp.o:(.bss._ZSt13__exidx_start+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\teensy41\firmware.elf] Error 1
Upvotes: 0
Views: 36