Link private library with arduino

Hi! I have some trouble with linking my private library to arduino platform.

I have an library for esp32/esp8266 with this library.json:

{
"name": "libname",
"desciption": "libdesc",
"keywords":"keyword",
"authors": {
    "name":"My Name",
    "mainteiner":true
},
"repository": {
    "type":"git",
    "url":"https://github.com/sobieg/libname.git"
},
"version":"1.0",
"license":"MIT",
"frameworks": "arduino",
"platforms": "espressif8266, espressif32",
"headers": "mainheader.h"
}

Inside i have a function, like

#include "Arduino.h"
int randombytes(unsigned char* random_array, unsigned long long nbytes)
{ 
    randomSeed(analogRead(0));
    for (unsigned long long i = 0; i<nbytes; i++) {
        random_array[i] = secureRandom(2, 4);
    }
    return 0;
}

I compile library in a project with this platformio.ini:

[env:esp12e]
platform = espressif8266
board = esp12e
framework = arduino
board_build.ldscript = eagle.flash.4m1m.ld


lib_deps =
    libname

lib_extra_dirs =
    /full/path/to/dir/with/private/libs/

And get an linker error:

/opt/homebrew/bin/platformio -c clion run --target upload -e esp12e

Obsolete PIO Core v5.2.3 is used (previous was 5.2.4)
Please remove multiple PIO Cores from a system: link

Processing esp12e (platform: espressif8266; board: esp12e; framework: arduino)

Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: link
PLATFORM: Espressif 8266 (3.2.0) > Espressif ESP8266 ESP-12E
HARDWARE: ESP8266 80MHz, 80KB RAM, 4MB Flash
PACKAGES: 
 - framework-arduinoespressif8266 3.30002.0 (3.0.2) 
 - tool-esptool 1.413.0 (4.13) 
 - tool-esptoolpy 1.30000.201119 (3.0.0) 
 - tool-mklittlefs 1.203.210628 (2.3) 
 - tool-mkspiffs 1.200.0 (2.0) 
 - toolchain-xtensa 2.100300.210717 (10.3.0)
LDF: Library Dependency Finder -> link
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 40 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <libname> 1.0
Building in release mode
Compiling .pio/build/esp12e/src/main.cpp.o
Compiling .pio/build/esp12e/lib206/libname/libsource.c.o
Linking .pio/build/esp12e/firmware.elf
/path/to/xtensa-lx106-elf/bin/ld: .pio/build/esp12e/lib206/liblibname.a(libsource.c.o):(.text.randombytes+0x0): undefined reference to `randomSeed'
/path/to/xtensa-lx106-elf/bin/ld: .pio/build/esp12e/lib206/liblibname.a(libsource.c.o):(.text.randombytes+0x4): undefined reference to `secureRandom'
/path/to/xtensa-lx106-elf/bin/ld: .pio/build/esp12e/lib206/liblibname.a(libsource.c.o): in function `randombytes':
libsource.c:(.text.randombytes+0x20): undefined reference to `randomSeed'
/path/to/xtensa-lx106-elf/bin/ld: libsource.c:(.text.randombytes+0x3b): undefined reference to `secureRandom'
collect2: error: ld returned 1 exit status
*** [.pio/build/esp12e/firmware.elf] Error 1
 [FAILED] Took 6.17 seconds 

Without adding this functions, library compiles, links and works fine, so what can i do to build my library with arduino functions?

You’re attempting to access a C++ function, secureRandom and friends, from C code. That doesn’t work that way due to C++ name mangling.

The function

will have the symbol name _Z12secureRandomll in GCC. Calling secureRandom from C code directly will expect that a symbol called secureRandom is there. It isn’t.

I suggest you rename libsource.c to libsource.cpp to gain normal access to the C++ functions and prefix all function prototypes with extern "C" to keep external C linking compatibility, if this code is supposed to be called from C.

extern "C" int randombytes(unsigned char* random_array, unsigned long long nbytes)
{ 
  //..
}

If your libsource.c must remain a C-source, you need to create a C-callable wrapper function in C++ through extern "C". There’s no way around that.

See Standard C++.

1 Like

Thanks! I think i can easy migrate to c++ for my lib.