I need to use the mbed api but limited to using C. How can I use for example a SPI class in a c file. From looking online to use C++ classes you should create a wrapper function in C++ but as stated I can't use C++, is their another way around this?
-
1Create a free function as interface to that class, and use `extern "C"`. https://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c – Jepessen Aug 09 '17 at 09:14
-
2You can not directly use C++ stuff in C. You need to write a C interface wrappers for C++ code first. – user7860670 Aug 09 '17 at 09:15
-
@Jepessen but that doesn't work for classes I thought – homeGrown Aug 09 '17 at 09:16
-
@VTT and those wrappers are in C++ yes? – homeGrown Aug 09 '17 at 09:19
-
@homeGrown: you may need more than one free function; typically one per member. (including constructor and destructor). – MSalters Aug 09 '17 at 09:20
-
Yes, those wrappers are in C++. But they only expose C stuff. – user7860670 Aug 09 '17 at 09:24
-
While C and C++ are inter-operable, if you cannot use C++ at all, then you cannot use the class - since first of all it _is_ C++, and you need to implement the C-linkage wrapper in C++. Why are you "limited to C"? That makes little sense. – Clifford Aug 09 '17 at 12:49
4 Answers
How can I use for example a SPI class in a c file.
You cannot use a class† in C.
From looking online to use C++ classes you should create a wrapper function in C++
This is correct.
is their another way around this?
No.
but as stated I can't use C++
Then you're out of options (as far as the standards are concerned). A C++ API (with classes and everything) cannot be used in C. It is possible to create a wrapper interface that uses only features shared by both languages (which excludes all OOP stuff).
That wrapper interface can only be implemented in C++, because it has to interact with the interface that it is wrapping. If the wrapper could be implemented in C, then there would be no need for it. Once that wrapper interface is implemented, it can be used from C.
Some other points:
- If a library uses C++, then
main
must be implemented in C++. Thatmain
can also be a trivial wrapper for a C function, which can be called from C++ without fuss. - You must link the dependencies of the C++ library, which may include the C++ standard library
Example:
C++ API
// interface.hpp
class C {
public:
std::string str;
};
C wrapper for the API
// wrapper.h
struct C;
struct C* makeC();
void freeC(struct C*);
void setStr(struct C*, char*);
conts char* getStr(struct C*);
Implementation of the wrapper (in C++)
extern "C" {
#include "wrapper.h"
}
#include "interface.hpp"
C* makeC() { return new C; }
void freeC(C* c) { delete c; }
void setStr(C* c, char* str) { c->str = str; }
const char* getStr(C* c) { return c->str.c_str(); }
Usage in C
struct C* c = makeC();
setStr(c, "test");
puts(getStr(c));
freeC(c);
†Except when the class definition and all of its sub objects use no C++ features whatsoever. Then it is compatible with an identical C struct.

- 232,697
- 12
- 197
- 326
-
*Theoretically* you could instantiate and use a C++ class with pure C if you knew the mangled names of the members. If it used any standard containers or other libraries, though, then it would probably fail spectacularly. – Bartek Banachewicz Aug 09 '17 at 09:23
-
2@Bartek Banachewicz - Bartek - it is a hack not the sane solution – 0___________ Aug 09 '17 at 09:33
-
The mbed HAL is written in C, so you can use that without the C++ wrappers. E.g. here is hal/spi_api.h.

- 26,598
- 9
- 83
- 120
-
Looks like exactly what I need. Is their any examples of how to get up and running with this on an arm board (st) – homeGrown Aug 10 '17 at 13:59
-
`spi_t spi; spi_init(&spi, SPI_MOSI, SPI_MISO, SPI_SCK, SPI_NSS); spi_frequency(&spi, 4000000); /* etc. */` The right implementation for your board is automatically loaded. – Jan Jongboom Aug 10 '17 at 15:13
-
-
The HAL automatically includes the right implementation for the board. For example, [here is the HAL for STM32F4](https://github.com/ARMmbed/mbed-os/blob/master/targets/TARGET_STM/TARGET_STM32F4/spi_api.c) (and this is loaded through `#define`'s. If you export a project to makefile then you can see all of them in there.) – Jan Jongboom Aug 11 '17 at 08:12
Answer is simply - using mbed involves using C++.
If you have to program in C forget about mbed and write your own SPI library or use one of the many available libraries (frameworks) for your target hardware.
There is no other way

- 60,014
- 4
- 34
- 74
-
2"There is no other way" is erroneous. And the answer provides no example whatsoever, so it's practically useless. – Fabien Aug 09 '17 at 09:56
If you are limited to use C... just use C and compile it as a C++ file. Most code shall be compatible.

- 43
- 4