[C-API] Converting string to float

Hey,
I'm trying to extract float values from a string, and using sscanf() seems to work well when building for the simulator, but when trying to build for the playdate it's throwing out these errors:

c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-writer.o): in function `_write_r':
writer.c:(.text._write_r+0x14): undefined reference to `_write'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-closer.o): in function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-lseekr.o): in function `_lseek_r':
lseekr.c:(.text._lseek_r+0x14): undefined reference to `_lseek'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-readr.o): in function `_read_r':
readr.c:(.text._read_r+0x14): undefined reference to `_read'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-abort.o): in function `abort':
abort.c:(.text.abort+0xa): undefined reference to `_exit'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-signalr.o): in function `_kill_r':
signalr.c:(.text._kill_r+0x12): undefined reference to `_kill'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-signalr.o): in function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-fstatr.o): in function `_fstat_r':
fstatr.c:(.text._fstat_r+0x12): undefined reference to `_fstat'
c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/progra~2/gnuarm~1/102021~1.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard\libc.a(lib_a-isattyr.o): in function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'

i tried atof() on a simpler string but that also doesn't seem to be working.

Anyone have any idea what I might be missing? Thanks!

Hi, I use sscanf without any issue both on Simulator and device.

The problem should be elsewhere, some C functions are not supported on Playdate (printf, asprintf, fopen).

See the following:

Undefined reference to `_exit' and friends

Interesting, you didn't need to set up anything special? If I comment out sscanf() it compiles fine for me so I'm really not sure what else it could be.

Thanks, I tried the advice in that thread of adding --specs=nosys.specs to line 145 in common.mk but it doesn't seem to be making any difference for me. Not sure if there's anything else I'm supposed to do, playing around with compiler settings is a bit out of my wheelhouse.. If it's any help, I'm using visual studio and set up my project exactly as the SDK guide told me to do.

Confirmed that sscanf() works with the nosys.specs thing. When I get home, I can try it on the hardware.

I'm not too familiar with Visual Studio, so I can't help you troubleshoot that. When I built it, I ran the make command from the project directory on a Debian environment.

Attached is the test program I made to try it out. It failed to build without the --specs=nosys.specs parameter as expected: sscanf.zip (72.2 KB)

It does the following:

  • Begin with the text "3.1415927"
  • Display the text on-screen
  • Process the text as a float
  • Multiply the value by 2
  • Format the result as text
  • Display the resulting text on-screen

screenshot

Per Dave's suggestion, snprintf() should be used instead of sprintf() for safety checking. I just used it because I know for sure it was also triggering the "undefined reference" errors. There is no snscanf(), unfortunately.

1 Like

thank you so much for setting up this example project! I tried compiling it the same way as I was mine, and got the same errors. At least this made me realize there was probably nothing wrong with my code, so I did a bit of digging around and found this discussion: How to cross compile with cmake + arm-none-eabi on windows? - Stack Overflow

I added set(CMAKE_EXE_LINKER_FLAGS "--specs=nosys.specs" CACHE INTERNAL "") to arm.cmake, and that did the job, compiling your project to run on the hardware!

I think this should solve my problem, thanks for the input everyone!

I didn't setup anything special but I'm on macOS, maybe it's different on Windows.