I try to convert my project to C++ in TrueSTUDIO for STM32 by
Selecting project (in C/C++ Projects tab)
Right mouse button, select New/Other
In C/C++ tab, Convert to a C/C++ Project (Adds C/C++ Nature)
When pressing Next, nothing happens (unclear why)
When I press Next again, I see: Convert to a C/C++ project: The wizards adds C/C++ Nature to the selected projects to enable C/C++ Tools Supports for them
I press Finish
Than nothing happens, when I change main.c to main.cpp, I get the following error after build:
startup\startup_stm32f407xx.o: In function `LoopFillZerobss':
C:\Users\Michel\OneDrive\Stm32\Stm32CubeProjects\Fcb1010\Debug/..\startup/startup_stm32f407xx.s:115: undefined reference to `main'
collect2.exe: error: ld returned 1 exit status
It seems still C is used (also in the command line (first part):
arm-atollic-eabi-gcc -o Fcb1010.elf Drivers\STM32F4xx_HAL_Driver\Src\stm32f4xx_hal.o Drivers\STM ...
I would expect g++ to be used.
How to change my settings/procedure to be able to use C++ within TrueSTUDIO for a CubeMX generated project?
UPDATE
I removed Atollic TrueStudio, removed AC6 System Workbench, and reinstalled AC6 System Workbench. Now I can use C++ at AC6 System Workbench, even using STL.
I do not dare to install Atollic TrueStudio again, since it breaks the existing installation of AC6 SystemWorkbench, probably because they both use Eclipse. A pity, since I liked some features of TrueStudio, but C++ is more important to me. So for me, no TrueStudio anymore.
The error you mention
startup\startup_stm32f407xx.o: In function 'LoopFillZerobss':
C:\Users\Michel\OneDrive\Stm32\Stm32CubeProjects\Fcb1010\Debug/..\startup/startup_stm32f407xx.s:115: undefined reference to `main'
collect2.exe: error: ld returned 1 exit status
Is a linker problem, I suspect the library is looking for a c main function. A C++ compiler performs name mangling, so the symbol will no longer be main.
Try changing the signature of your main to extern "C" int main(void)
Please follow below steps:-
Better convert all the .c file to .cpp manually
Check each header file and change macro which is specific to C language
change the main function from C type to C++ (void main to int main()) also return a value from your main function.
If you are using a make file check if specific C dependencies are referred and change them.
Hope this will help.
Related
I have started learning C++ on Ubuntu. I am only a few months into using Linux as well.
I am attempting to port over a 2D Ball Collision Script from Javascript to C++ for learning purposes.
I am using simple2D for the drawing in C++: https://github.com/simple2d/simple2d
I go to run this command:
simple2d build c-code-test.cpp
I receive this response:
cc1plus: warning: command line option ‘-std=c11’ is valid for C/ObjC but not for C++
/usr/bin/ld: /tmp/ccl07DBG.o: undefined reference to symbol '_ZNSt8ios_base4InitD1Ev##GLIBCXX_3.4'
//usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
Due to how fresh I am with Linux and C++ I am unable to make the correct inferences to solve this based on previous questions on stack overflow. I have installed libstdc++6 so I would have though it would be linked correctly.
Can someone walk me through in steps 1, 2, 3 ... Please? Thank you kindly!
The errors you see look to be from trying to compile C++ as C. The command line option is selecting the C11 standard, which is for C, not C++. The missing symbol is because the C++ library isn't being linked in, which also happens when linking a program as C.
I haven't used simple2d, but my guess here is that the compile script they wrote does not support C++ or there is some option you need to use C++. If we look at docs:
The simple2d build command is a helpful shortcut for compiling a
single source file. Of course, you can also use a compiler directly,
for example on Unix-like systems:
cc triangle.c `simple2d --libs` -o triangle
Why don't you try something like their example that invokes the compiler directly. But you would need to use g++ instead of cc. Something like: g++ c-code-test.cpp `simple2d --libs` -o c-code-test
This is a bug with the simple2d script.
They're basically using the wrong build command for C++.
You could work around it by patching in the fix I've linked to, or using the manual build step shown by TrentP.
Or wait for the next version after v1.1.0.
I am using Eclipse kepler for AVR development.
The code that I have is C (Open Source), and I've gotten it adjusted so it runs perfectly. My target is an ATmega2560, in the form of an arduino mega2560.
Using the arduino board is strictly for hardware convenience; we are developing the hardware to be a custom board with most of the core arduino mega2560 components.
I need to use several libraries with this project that are only available as arduino libraries, namely libraries for an e-paper screen (from seeedstudio) and Nordic's BLE nRF8001.
If I create a new arduino project using the plugin in eclipse, I can build and run the tests for the arduino libraries perfectly.
When I try to merge the 2 code bases together, I can't seem to call the functions in the added arduino libraries - if I call them the compiler throws a linking error.
Building target: Virgin2ManualArdInsert.elf
Invoking: AVR C Linker
avr-gcc -Wl,-Map,Virgin2ManualArdInsert.map -mmcu=atmega2560 -o "Virgin2ManualArdInsert.elf" ./avr/adc.o ./avr/eeprom.o ./avr/lcd_and_input.o ./avr/main.o ./avr/strings.o ./avr/unimplemented.o ./avr/usart.o ./aes.o ./baseconv.o ./bignum256.o ./ecdsa.o ./endian.o ./fft.o ./fix16.o ./hash.o ./hmac_sha512.o ./messages.pb.o ./p2sh_addr_gen.o ./pb_decode.o ./pb_encode.o ./pbkdf2.o ./prandom.o ./ripemd160.o ./sha256.o ./statistics.o ./stream_comm.o ./test_helpers.o ./transaction.o ./wallet.o ./xex.o
./avr/main.o: In function `main':
main.c:(.text.startup.main+0xc): undefined reference to `writeEink'
collect2: error: ld returned 1 exit status
makefile:53: recipe for target 'Virgin2ManualArdInsert.elf' failed
make: *** [Virgin2ManualArdInsert.elf] Error 1
As a test, I'm just trying to call a basic "write to display" call in eInk.cpp from main.c:
extern "C"{
void writeEink()
{
EPAPER.begin(EPD_SIZE); // setup epaper, size
EPAPER.setDirection(DIRNORMAL); // set display direction
eSD.begin(EPD_SIZE);
GT20L16.begin();
// int timer1 = millis();
EPAPER.drawString("testing", 10, 10);
EPAPER.drawNumber(12345, 60, 40);
EPAPER.drawFloat(-1.25, 2, 80, 65);
EPAPER.display(); // use only once
}
Is a static library built from the arduino cores the way to go here? I've tried it (though it seems most of the procedures are outdated) and the libraries do not want to link/be called.
What is the correct procedure for including C++/Arduino calls in my C code?
I've tried using extern "C" {function()}; in my .cpp files and .h files but to no use.
Thank you for any help or pointers to where I can figure it out for myself.
You can try to compile your C code as C++ by simply renaming the files to *.CPP, but chances are that you have to modify your code to make it compile as C++ code. There are things that are allowed for C, but not for C++ (like calling functions that are not declared).
The other solution is to wirte wrappers around the C++ functions that you want to use from C.
You have to consider two limitations of C against C++:
C is not object oriented
C does not support overloading of functions
This example for Serial.print() shows how you can handle this with a wrapper:
extern "C" void SerialPrintInteger( int value )
{
Serial.print( value );
}
In this example you would write similar functions like SerialPrintFloat(), SerialPrintString() etc.
The extern "C" prefix tells the compiler to create the function in a way that makes it callable from C.
The error you received above isn't a compiler error, it's a linker error. I haven't used Eclipse for Arduino development, I just stick with the Arduino IDE, but the standard Arduino projects expect all of your code to be in a single source file, which it compiles and then links with the Arduino libraries. Arduino programs don't have a C/UNIX-style "main" function, the standard functions are "setup" and "loop."
I recommend going back to one of the Arduino example programs, blink for instance, and watching the console log as Eclipse compiles and links the program. What's happening here is:
The C/C++ compiler compiles your source code, including setup(), loop(), and any other functions you have created, into an object file.
The Linker links this single object file with the Arduino runtime, and any Arduino libraries you have specified. The output of this is an image of the program, in your example above it's trying to make 'Virgin2ManualArdInsert.elf'.
The uploader (probably avrdude) loads this image into your Arduino and resets it.
The Arduino comes out of reset and runs your new code.
If your program is reasonably small, say not more than a few hundred lines, just put all the functions in the one source file, then you won't have to learn how to drive the linker.
If you need, for some reason, to have the sources in a separate file (maybe they're shared with another program, or another platform), then you'll have to learn how to get Eclipse to link the object files from your multiple source files. This may just involve adding the sources into your Eclipse project properly, or you may have to write a Makefile or something similar.
As for C vs C++ source code, you can usually drop a C function into a C++ source file and compile it. There are a few differences, but this way you don't need to worry about "C" linkage or any of that silliness.
I have been running into trouble recently trying to symbolicate a crash log of an iOS app. For some reason the UUID of the dSYM was not indexed in Spotlight. After some manual search and a healthy dose of command line incantations, I managed to symbolicate partially the crash log.
At first I thought the dSYM might be incomplete or something like that, but then I realized that the method calls missing were the ones occurring in C++ code: this project is an Objective-C app that calls into C++ libraries (via Objective-C++) which call back to Objective-C code (again, via Objective-C++ code). The calls that I'm missing are, specifically, the ones that happen in C++ land.
So, my question is: is there some way that the symbolication process can resolve the function calls of C++ code? Which special options do I need to set, if any?
One useful program that comes with the apple sdk is atos (address to symbol). Basically, here's what you want to do:
atos -o myExecutable -arch armv7 0x(address here)
It should print out the name of the symbol at that address.
I'm not well versed in Objective-C, but I'd make sure that the C++ code is being compiled with symbols. Particularly, did you make sure to include -rdynamic and/or -g when compiling the C++ code?
try
dwarfdump --lookup=0xYOUR_ADRESS YOUR_DSYM_FILE
you will have to look up each adress manually ( or write a script to do this ) but if the symbols are ok ( your dSym file is bigger than say 20MB) this will do the job .
My project has a function that clears the terminal, which is implemented using the curses library. Compiling with the -lcurses flag works fine, but compiling without yeilds
/tmp/cc3T2MVI.o: In function `ClearScreen()':
clear_term.cpp:(.text+0xb): undefined reference to `cur_term'
clear_term.cpp:(.text+0x26): undefined reference to `setupterm'
clear_term.cpp:(.text+0x37): undefined reference to `tigetstr'
clear_term.cpp:(.text+0x3f): undefined reference to `putp'
collect2: ld returned 1 exit status
This is obviously expected because it cant find the library, but because this functionality is supplemental it would be preferable to define ClearScreen() as an empty function than to have compilation fail. I know that I put the function definition in a #ifdef block but I don't know any flags defined by curses.
Is it possible to catch these errors and instead define ClearScreen() as an empty function?
You can define a macro in the Makefile:
use_curses=1
FLAGS+=-DUSING_MAKEFILE
ifeq ($(use_curses),0)
FLAGS+=-DNO_NCURSES
else
LIBS+=-lcurses
endif
And in the code:
#ifndef USING_MAKEFILE
# error "Please use provided Makefile to compile!"
#endif
#ifdef NO_CURSES
void ClearScreen() { }
#endif
Actually, that is a linker error. And no, it can't really be caught at compile time. But one possibility would be to load the shared object dynamically in ClearScreen. If it failed to load the library, then it could just return. Doing the check at run time may be preferable to build time checks if you are not guaranteed to be building the binary on the target system on which it will ultimately be running.
You really need this library.
Maybe it will help you: http://linux.die.net/man/3/tigetstr
What you are trying to do (configuring the project with respect to dependencies) — is the classical task of build systems.
For example, with CMake, you'll have FindCurses module, which defines CURSES_FOUND preprocessor variable (if it founds the library).
With GNU Autotools you'll have similar macro, consult the relevant documentation.
If you're using your own build system — then you have to manually code the handling of relevant flags in configuration time.
Your build script should detect whether a suitable version of curses is present on the build machine. You can generate such script with GNU Autotools for example (the result iwould be a familiar configure script. You can also write a simple custom script insh/bash.
The problem you haven't considered is that your code probably #include's ncurses.h, which won't ever work without the library being installed where the compiler can find it.
I'm a novice at C++. Be patient if this is incoherent. I'm called upon to build a large system on linux that was originally built on OS X, where it works fine. The original authors are no longer with the company. The build system makes use of autotools, but there are also some hand made Makefiles which walk through the system calling the auto-made Makefiles. I've managed to get all of the c++ code compiled. The build system also uses libtools, and shared libraries are produced and deposited in /usr/local/lib.
So now I'd like to use these libraries. I've written a short program that simply instantiates an object of class ds_dictionary and calls one of its methods. Here it is:
#include <iostream>
#include <DSUtils/DSUtils.h>
int main (int argc, char * const argv[]) {
int32_t integer_data=123;
char key_alice_integer[] = "alice_integer";
ds_dictionary my_dict;
my_dict.add_int(key_alice_integer, integer_data);
return 0;
}
I compile this with
g++ -lDSUtils -o main my_test_code.cpp
With the result:
//usr/local/lib/libDSUtils.so: undefined reference to `ds_breakdown_from_time_interval'
//usr/local/lib/libDSUtils.so: undefined reference to `ds_date_breakdown_with_string'
//usr/local/lib/libDSUtils.so: undefined reference to `ds_seconds_duration_of_interval'
... (about 25 lines like these)
collect2: ld returned 1 exit status
Let's look inside the library:
garyp#VM:/usr/local/lib$ nm libDSUtils.so | grep ds_breakdown_from_time
U ds_breakdown_from_time_interval
The "U" in the line above ... does that mean that the library wasn't built correctly?
Am I calling g++ correctly?
Do I have to put something in the code to tell it that I'm using functions found in that library?
What are possible errors? Where should I start poking around?
EDIT:
Aha. The library DSUtils is built from several c++ sources. There is one c program in the source, and it contains all of the problem functions. The Makefile system doesn't deal at all with that one c file. That c program compiles. Ideally I suppose I'd figure out how to modify the Makefile to compile that file and add it to the library, but I'm not to the point where I can figure out how to do that.
Can I add the .o file to the existing library? How? Create a library with one file? etc?
EDIT_2: I simply did
g++ -o main -lDSUtils main.o my_new_objectfile.o
and the thing compiles, links, and runs without error. Should that work? After fixing a logic bug, it does work.
This
U ds_breakdown_from_time_interval
tells me that ds_breakdown_from_time_interval will be resolved by another library during runtime. So I am guessing you need to link to the library that defines ds_breakdown_from_time_interval.