Skip to main content
Harvey White
Senior III
August 24, 2019
Question

Cube32 feature request, need to handle CPP files.

  • August 24, 2019
  • 8 replies
  • 7187 views

The support of CPP architectures in Cube32 is limited. While it would be nice if Cube32MX actually had CPP libraries, that's a long step.

It's very possible, however, to integrate a C++ layer on top of the existing code, where C++ routines call C routines.

However the process is limited by one feature in Cube32MX, and that is the dependence on main.c. How about a very small rewrite so that once there *is* a main.cpp, Cube32MX can make changes to it. Shouldn't be hard to do. Change main.c if it exists in the project, if it doesn't, then look for main.cpp and change it.

This will stop errors caused by forgetting to rename main.cpp back to main.c so that adjustments can be made, and then back from c to cpp.

8 replies

Pavel A.
Super User
August 24, 2019

The code generated by CubeMX and all the libraries are plain C.

IMHO renaming main.c to cpp will annoy many people who are comfortable with C.

An option in Eclipse project generation to add the "C++ nature" would be just enough.

Then users can add c++ files to the main C file, and bring their c++ libraries and stuff.

-- pa

Harvey White
Senior III
August 24, 2019

I agree with you, the libraries are plain C and can stay that way unless they get rewritten (and it's an option for STMicro).

There is already an option to add the C++ nature to a C project, it adds the C++ compiler and options, but does somewhat of a poor job in really configuring the environment for C++. That wasn't the idea. I already did that, and with a lot of tweaking here and there, it works, and works reliably. That's the C++ part of it.

However, the idea about renaming main.c to main.cpp works like this.

IF you have a main.c file, CubeMX does no renaming, and regenerates the file as needed. Thus, the C users will not be annoyed.

IF you have a main.cpp file, CubeMX does not rename it, that was for you to do once. CubeMX will regenerate the .cpp file as if it were renamed main.c

CubeMX already handles a renamed main.cpp (if it's in C) file without a problem. However, currently, you have to rename it yourself, then name it back again.

It's easy for C++ to call C files, I haven't found an easy way for C to call C++. Easy is defined as "it just does it without me having to do anything". Adding the C++ nature to the project is an easy one time step, and lasts even when the files are regenerated by CubeMX. So we're almost there.

What I would like is that CubeMX recognizes a .cpp file as valid, specifically main.cpp, and modifies it without having to rename it.

Piranha
Principal III
August 25, 2019

> libraries are plain C and can stay that way unless they get rewritten (and it's an option for STMicro)

They must be rewritten, but "C++ only" is definitely not an option. But anyway before going to higher layer code, ST must first learn basic C and make actually working, not bloated and flexible drivers in plain C. HAL is not even near to that!

Piranha
Principal III
August 25, 2019

> It's easy for C++ to call C files, I haven't found an easy way for C to call C++.

Internet is full of examples:

http://www.jonathanbeard.io/tutorials/Mixed_C_C++

https://stackoverflow.com/questions/2744181/how-to-call-c-function-from-c

https://isocpp.org/wiki/faq/mixing-c-and-cpp

In short - leave main.c as a C file and call C++ functions from there.

Harvey White
Senior III
August 25, 2019

Solved, but (and thanks Piranha) it took all three links to construct a workable solution, since each solution makes assumptions about the environment.

My exact solution is to do as little to main.c as possible (I've got an application structure defined in C++, and I want to be able to copy the user sections of main.c to another main.c without having to worry about the project name and type. To do this, I have a small function called cpp_link which calls the application init. The application init is in a different file, the cpp_link call from main remains constant for all projects. What cpp_link calls is constant, but the include file for cpp_link pointing to the application varies per application (if needed, keeping constant names over projects can be a help). This is a FreeRTOS environment, and the latest Atollic studio (V9.3.0).

This is using main.c as generated by CubeMX (and no, I don't want to work with the registers and LL drivers right now, did that on an Xmega, got the T shirt, T shirt's a rag).

the code for the body of cpp_link.cpp is:

#ifdef __cplusplus
	extern "C"
	{
#endif
	void cpp_link (void)
		{
			APPLICATION_init();
		}
#ifdef __cplusplus
	}
#endif

You not only need the extern "C" declaration, but it must have the #ifdef statements surrounding it. You get errors without the #ifdef statements.

The corresponding declaration in cpp_link.hpp is

#ifdef __cplusplus
	extern "C"
	{
#endif
	void cpp_link (void);
#ifdef __cplusplus
	}
#endif

Again, note the syntax and the inclusion of the #ifdef statements

In the main program do the following: What you have here is your own task that takes the place of the main task loop. That task loop is all C++, as is cpp_link and the application_init code. The intention is that you start up your main task for the application, and do not use the main program loop. This allows you to adjust the task size independent of the CubeMX settings for FreeRTOS. Note that the main task loop in main.c ticks over very slowly.

So the last code that you need is in main.c.

 /* USER CODE BEGIN 5 */
 /* Infinite loop */
	 cpp_link();
	 // cpp_link goes to application init
	 // main task does nothing
 for(;;)
 {
 osDelay(10000);
 }
 /* USER CODE END 5 */ 

This partitions your application loop and keeps it away from main.c, giving you a minimum amount of things you have to do to main.c to get it to work. You can likely just copy main.c from project to project, regenerate it with CubeMX, keeping all the settings you need, and not worry about the project or the rest of the setting, since they're all in your C++ code.

I would *still* like to see CubeMX deal gracefully with a C++ main file, though.

Pavel A.
Super User
September 7, 2019

> This partitions your application loop and keeps it away from main.c, giving you a minimum amount of things you have to do to main.c to get it to work.

Yes, exactly this.

> I would *still* like to see CubeMX deal gracefully with a C++ main file, though.

IMHO here is how this can be done in the way acceptable for conservative users like myself:

If instead of main.c there is main.cpp (assume the user renamed it) - just keep treating is as plain C.

Let the smart user manage all these extern "C", #ifdef cplusplus and so on in user code sections.

-- pa

Harvey White
Senior III
September 7, 2019

We agree completely. Now all we need to do is to wait until ST Micro twigs this as a solution (trans: sees that this works, decides to do it, and so on) and then the problem is solved.

In the meantime, my particular solution for my architecture hasn't broken yet, and seems to be a reliable solution. NOT (I think) that we OUGHT to have to do this, or find a workaround. It is, however, what we have to deal with.

Still, let's hope that people in similar situations find this situation reasonable.

As a note: I would have been more or less (less because of program structure) happy to allow and use only C. However, the program is complex enough (a rather involved graphics application) that the C++ class would have been very helpful (graphics_object -> point -> line -> panel -> button with various divergences from the path.) If this isn't what you do (and not likely) then you may want to look at the architecture to see *if* C++ and class inheritance could help.

saying that, though, there are problems and system architectures where C++ makes life a lot easier. It also complicates some things as well.

The utility of C++ for a project depends on the architecture, the size and the point at which you decide that there *ought* to be an easier way to do this.

Where the program was for me, was at the point wher I decided that there had to be an easier way, that a redesign was needed, and that (for me) the redesign worked.

And no, you won't learn this from very many places, practice and experience seem to be a good thing.

I also wouldn't (personal opinion) say that "I don't need C++, C is good enough).

I did the same thing with assembly, then C, and now C++ as the project evolved...

Each upgrade (rewrite with a different language) brings advantages and disadvantages. It's up to you to figure out what to use and where (if anywhere) to stop.

Harvey White
Senior III
March 12, 2023

I understand. That, of course, explains why the class definitions in .hpp files cause the C compiler to throw up all over the listing. Have you a suggestion to fix that other than making sure that the path to that file is only in the C++ file paths?

Piranha
Principal III
March 12, 2023

The *.c files should include only those *.hpp files, which are specifically made to be shareable between the C/C++ and use the #ifdef __cplusplus and extern "C" appropriately.

Gaston
Associate III
May 28, 2024

However the process is limited by one feature in Cube32MX, and that is the dependence on main.c. How about a very small rewrite so that once there *is* a main.cpp, Cube32MX can make changes to it. Shouldn't be hard to do. Change main.c if it exists in the project, if it doesn't, then look for main.cpp and change it.

It must be very difficult, extremely complicated.
After 5 years of this post, we are still renaming main.c to main.cpp...