Specifying device specific functions in struct - c++

I am working with firmware, trying to make a device-independent library. The library uses I2C to communicate, a simple and common protocol for those who don't know what it is. I2C uses two functions that I"m concerned with, read and write. Using I2C on different microcontrollers and such is different for each core mainly and I'm looking for a way for the library to be passed the functions so it can use them in a consistent manner.
How can I make a struct that a user can set variables to functions.
Something like:
typedef struct I2C_setup{
function read = device specific read function;
function write = device specific write function;
}
and then I could call
I2C_setup I2C;
And thereafter
(return type) RegisterRead = I2C.read(register address);
Would I use function pointers or...what?

Function pointer is a good idea. You can defined your prototype as
typedef struct I2C_setup{
(*I2C_Read_Func)(uint32_t devAddr, uint32_t subAddr, uint8_t *pData, size_t lenght);
}
your actual function as
I2C_Read(uint32_t devAddr, uint32_t subAddr, uint8_t *pData, size_t lenght);
and you can assign it by
I2C_setup I2C;
I2C.I2C_Read_Func = I2C_Read;

Related

C++ classes vs. C different files

Currently in a project there is a clear set of functions that pertain to a clear responsibility. Because the responsibility is a periodic process that requires buffers and counters for each iteration, I have to reset the variables used by those functions after each cycle. The variables are mostly static because per cycle the functions are called thousands of times. (It is a set of digital FIR filters that process the 5 second data that is coming in every 2 minutes or so). The variables have to be declared in the file scope, because the functions share them. E.g. the reset / initialize function and the actual filter functions.
As of now, the whole project is in C (but C++ is easily supported, as the possibly breaking parts already contain 'extern C {}'). To make the code cleaner, I thought to group the functions and variables in a separate implementation file. But of course, I could also use C++ classes, which I would like to work with more.
What are the essential differences between these options?
Simplified example of what I mean:
In this example, I just kept the structure of the program. The Filter() function is called for example 1000 times in 5 seconds for the first iteration. Then for the next iterations, the Reset() function is called prior to the actual Filter() function calls, to reset all the buffers that are used.
// File-scope variables
static float buffer[BUFFER_SIZE];
static uint8_t bufferOffset = 0;
// Filter
static float Filter (const float sample)
{
buffer[bufferOffset] = sample;
// Removed actual filter code here
return result;
}
// Reset functions
static void Reset (void)
{
memset(buffer, 0, sizeof(buffer));
bufferOffset = 0;
}
The usual approach in C to avoid those shared states is to define a structure encapsulating all the relevant state, pass it to every function and operate solely on it.
Example:
// buffer.h
#pragma once
// opaque data structure whose content
// isn't available to the outside
struct buffer;
// but you may allocate and free such a data structure
struct buffer *alloc_buffer();
void free_buffer(struct buffer *b);
// and you may operate on it with the following functions
float filter_buffer(struct buffer *b);
void reset_buffer(struct buffer *b);
void add_to_buffer(struct buffer *b, const float *data, size_t size);
And the source looks like this:
// buffer.c
#include "buffer.h"
struct buffer {
float content[BUFFER_SIZE];
uint8_t offset;
}
struct buffer *alloc_buffer() {
return malloc(sizeof(struct buffer));
}
void free_buffer(struct buffer *b) {
free(b);
}
float filter_buffer(struct buffer *b) {
// work with b->content and b->offset instead
// on global buffer and bufferOffset
return result;
}
void reset_buffer(struct buffer *b) {
memset(b->content, 0, BUFFER_SIZE);
b->offset = 0;
}
void add_to_buffer(struct buffer *b, const float *data, size_t num) {
memcpy(b->content + b->offset, data, sizeof(float) * num);
b->offset += num;
}
Thus you avoid a global state which for example dramatically simplifies multi-threaded applications of your code. And since you return an opaque data structure, you avoid leaking information about the internal structure of your buffer.
Now you may use this data structure in a different source file:
#include "buffer.h"
int main() {
struct buffer *const b = alloc_buffer();
// b->content[0] = 1; // <-- error, buffer is an opaque data type and
// you may only use the functions declared in
// buffer.h to access and modify it
const float data[2] = { 3.1415926, 2.71828 }
add_to_buffer(b, data, sizeof(data) / sizeof(data[0]));
const float result = filter_buffer(b);
return 0;
}
To answer you question: Even though you could separate your functions and global state even further into several compilation units, in the end you still have a shared global state. Except in some special cases I consider this a code smell.
The above described solution more or less corresponds to a C++ solution. You define a class encapsulating some state and methods operating on it. All instantiated objects are independent from each other.
To declare static file scope variables is the simplest form of private encapsulation. Such design is particularly common in embedded systems and hardware-related code. It's perfectly OK practice in a single-threaded program where there is just one single instance of the module/ADT that uses the variables ("singleton pattern").
Given your simple example, this should be just fine for your specific case. The art of program design is to know when to add extra layers of abstraction and when to avoid them. It isn't easy to teach, this mostly comes with experience.
A rule of thumb for the inexperienced programmer: if you are uncertain how to make the code more abstract, then don't add that extra abstraction. It is very likely to cause more far harm than it does good.
In case the code turns more complex, the next level of abstraction is simply to split it into several related files. Or rather into several .h + .c file pairs.
The point where this turns burdensome is where you need multiple instances of the module doing the same thing. Suppose you need multiple filters using the same code, but getting called by unrelated caller code. Having one set of static variables won't work then.
The sloppy but old school way of taking such abstraction further in C is to make a struct definition visible to the caller, then provide an interface such as void fir_init (fir_t* obj); where obj is allocated on the caller-side. This solves the multiple instances problem, but breaks private encapsulation.
The professional design would rather be to use the concept of opaque types (which is explained in multiple posts elsewhere on this site), where you only expose an incomplete struct type to the caller and let your module handle the allocation. This gives true OO design - you can declare multiple instances of the object while maintaining private encapsulation.
The C++ equivalent of opaque type is class and abstract base classes behave in exactly the same manner as opaque types in C - the caller can declare a pointer/reference to one, but not declare an object. C++ also provides constructors/destructors, which is more convenient than calling some "init" function manually. But this also leads to execution overhead when static storage duration objects have their default constructors called at start-up.
Also, C++ member functions come with their this pointer, so you don't need to pass a pointer to the object along manually. You can also have static members in a class and they behave just like C file scope static, with a single instance shared between all instances.

How can I expose C++ function pointers in C?

I have two types of function pointers defined in my C++ that look like this:
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
Class Core{
...
void myfunc1(LogFunction lg1, CallbackFn callback, int x, std::string y);
};
and I want to be able to expose them in C but I can't seem to find a way to do so. My first try was to cast these as void* and then recast them back to their actual type. but this seems like a bad idea. So I'm clueless as how to go about this conversion.
Also the solution that I need to come-up with should be doable using C++11 at the very least.
Update:
Thank you very much for your answers. However I need to add a bit more explanation as what I'm after. I know about extern "C" and in fact the C++ functions are exposed using this already in my DLL. However, the problem I had was to pass the function pointers back and forth between the C and C++.
One way was to define function pointers in a way that can be directly usable by C. That is I needed to change for example :
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
typedef std::function<void(std::string)> LogFunction;
to its C compatible one :
typedef void(*CCallbackFn)(bool, char*, int, unsigned char, int length);
typedef void(*CLogFunction)(char* string, int length);
and use these instead. However, the disadvantage of doing this is that, the DLL is also used by C++ clients and this would be a hindrance to change everything C++ to be compatible by C, I'd lose the advantages of C++ by doing this.
Instead I though of coming up with a second way. The C++ stays the same, but for C linkage and interacting with other languages through C API, I do the conversion myself.
That is they use C style and then I convert this back to C++ in the implementation part. In order to further simplify this so I designed some defaults on C++ part as well. Meaning, suppose for the lack of a better example, the instance needs a callback function to log whatever happens. I define a callback function in case it was not given by the user and create two functions for C API specifically something roughly similar to this:
//in core.cpp for example
include "Core.h"
...
extern "C"
{
Core * core;
...
Core_API void* get_default_log_callback()
{
return (void*) core->SomeDefaultCallback();
}
Core_API void* set_log_callback(void* fn)
{
// convert/cast that to the c++ callback type
// CallbackFn,
core->SetCallback(fn_converted);
}
and the client could for example use the get_default_log_callback and use its return to set_log_call_back.
Basically the idea here is to be able to use the C++ already defined assets.
I was stuck at this conversion process, how to convert such callback pointers to a C compatible type ( like what I showed, it'd be really easy to just cast the pointer to void* for example and write a C wrapper that accepts void* and then recast it to the proper type.
I'd like to know about this scenario as well and whether this is a good practice or the otherwise a bad one.
Question two:
Also I'd like to know if it is possible to have a conversion from for example the CCallbackFn and CallbackFn?
Suppose I've got a function(my C function above e.g.) in a CCalbackFn form ,but I want to ultimately have it in CallbackFn form(change it and call the underlying C++ that accepts CallbackFn) ? is this possible ?
C doesn't do / cannot handle C++ name mangling (nor C++ types that are not identical to C types). You cannot use non-POD types (and plain function pointers involving types not usable in C) in anything exposed to C. And you need to use extern "C" for the exposed stuff, to disable name mangling (or rather, use whatever naming convention/mangling your current platforms C compiler uses).
In short: use extern "C" for anything that must be callable from C and make sure anything exposed that way only uses types that you can write/use in C.
You can expose a function to C by declaring it extern "C".
However, the function must only accept argument types that are valid in C.
From the look of the code above, you're going to have to express your callback in more C-like terms.
In order to expose any C++ functions to C, you should wrap the C++ calls in C functions in a plain C++ library. And export only the C functions from it. Use a common header for C functions declarations inside and outside the library. These functions will be callable from any C environment. All the C++ types wrap in a class and pass a pointer to that class across function wrappers, as a handle to C++ environment. The pointer to class should be void* or just long. And only in C++ side you will reinterpret it to own environment class.
Update 1:
You should keep C and C++ separated. It means don't do conversions between C and C++. Keep separated C versions and C++ versions of XX_log_callback functions. For instance your C++ functions uses std::string, py::array_t&. There is no way you can use it is C. No conversion available, and no way to take advantages of it in C. You can take advantage of C++ only in C++, so make a separate version for C++ only and one available for C developers.
This is a by the way. There is a technique of passing around C++ interfaces to C and back to C++. But be attentive, it uses only C compatible return and argument types. It means creating a structure with a pointer to a table of function pointers. In C++ it is an interface but in C it is a struct. This technique is used in COM/OLE2 in Windows. https://www.codeproject.com/Articles/13601/COM-in-plain-C To use such a technique you should understand very well how to make a C++ class compatible with a C struct.
Now I will just copy/paste some pieces of code from the codeproject with little explanations.
The rule of thumb when passing interfaces between C and C++, use only types compatible with C as function arguments and as return type. The first four bytes in the interface is a pointer to an array of functions, called Virtual Table:
typedef struct
{
IExampleVtbl * lpVtbl;//<-- here is the pointer to virtual table
DWORD count;//<-- here the current class data starts
char buffer[80];
} IExample;
Here you add the pointers to functions in the virtual table. The IExampleVtbl is a structure filled with pointers, and binary it is equivalent to a contiguous array of pointers
static const IExampleVtbl IExample_Vtbl = {SetString, GetString};
IExample * example;
// Allocate the class
example = (IExample *)malloc(sizeof(IExample));
example->lpVtbl = &IExample_Vtbl;//<-- here you pass the pointer to virtual functions
example->count = 1; //<-- initialize class members
example->buffer[0] = 0;
Now this is how you call the methods:
char buffer[80];
example->lpVtbl->SetString(example, "Some text");
example->lpVtbl->GetString(example, buffer, sizeof(buffer));
Keep in mind, all of above is C.
In the above example you refer explicitly the virtual table member, and also you pass it explicitly as first parameter in the functions. The C++ equivalent of call to GetString/SetString is:
example->SetString("Some text");
example->GetString(buffer, sizeof(buffer));
Here is the SetString/GetStrinf functions and the virtual table structure:
HRESULT STDMETHODCALLTYPE SetString(IExample *this, char * str)
{
memcpy(this->buffer, str, length);//be attentive, it is almost pseudocode
return(0);
}
HRESULT STDMETHODCALLTYPE GetString(IExample *this, char *buffer, int buffer_len)
{
memcpy(str, this->buffer, length);//be attentive, it is almost pseudocode
return(0);
}
typedef struct {
SetStringPtr *SetString;
GetStringPtr *GetString;
} IExampleVtbl;
The STDMETHODCALLTYPE is to make it compatible with C++ calling of member function classes, so you will be able to pass the IExample between C and C++. I believe this will be really a nightmare for the C programmers, but not an easy task for C++ counterparts.
To access that when interface is passed from C, you declare interface like this:
class IExample
{
public:
virtual HRESULT SetString(char * str) = 0;//<-- see first parameter gone away in both functions
virtual HRESULT GetString(char *buffer, int buffer_len) = 0;
};
If you implement in C++ to pass in C equivalent of above code will be:
class IExample
{
int count = 1; //<-- initialize class members
char buffer[80] = "";
public:
virtual HRESULT SetString(char * str)
{
memcpy(this->buffer, str, length);//be attentive, it is almost pseudocode
return(0);
}
virtual HRESULT GetString(char *buffer, int buffer_len)
{
memcpy(str, this->buffer, length);//be attentive, it is almost pseudocode
return(0);
}
};
One more thing. You don't use the C declaration in C++ and vice-versa. This is by the COM approach to address the issue. It might be not portable to different compilers but keep in mind, similar approach is done in the old CORBA. Only you should keep in mind. You create one interface for C and one for C++. On C++ part hide the C interface and on C hide the C++ interface. Pass around only the pointers.
I ultimately came up with my own solution which I myself refer to as "Delegating Callbacks" approach! The idea here is that, instead of directly use the C callback, you create a diversion, you create an intermediate callback that acts as a translator between the two APIs.
For example, suppose my C++ class has a method that accepts only callbacks with this signature :
typedef void(*CallbackFn)(bool, std::string, py::array_t<uint8_t>&);
And now we want to expose this to C. and this is our C callback signature :
typedef void(*CCallbackFn)(bool, const char*, unsigned char*, int rows, int cols);
Now how do we go from the first to the second one or vice versa? We create a new callback in our C++ class of type CallbackFn, and inside it execute the C callbacks. So using an indirect call, we can easily decouple the signatures between the C and C++ APIs and use the ones that are most suitable for each.
To make it more concrete we need to have something like this:
CORE_API void Core::DelegateCCallback(bool status, std::string id, py::array_t<uint8_t>& img)
{
//here is used a std::map to store my c-callbacks you can use
//vector or anything else that you like
for (auto item: this->callbackMap_c)
{
//item.first is our callback, so use it like a function
item.first(status, id.c_str(), img.mutable_data(), img.shape(0), img.shape(1));
}
}
And you update your C callback list like this, using two exposed functions, Add and Remove to add and remove any callbacks respectively :
extern "C"
{
//Core is our C++ class for example
Core* core = nullptr;
...
CORE_API void AddCallback(CCallbackFn callback)
{
core->AddCallback_C(callback);
}
CORE_API void RemoveCallback(CCallbackFn callback)
{
core->RemoveCallback_C(callback);
}
}
and back in our C++ class, AddCallback_C methods are defined like:
CORE_API void Core::AddCallback_C(CCallbackFn callback)
{
auto x = this->callbackMap_c.emplace(callback, typeid(callback).name());
}
CORE_API void Core::RemoveCallback_C(CCallbackFn callback)
{
this->callbackMap_c.erase(callback);
}
Just adding/removing the callback to the callback list. That's all.
Now when we instantiate our C++ Code, we need to add the DelegateCCallback to the callback list, so when all C++ callbacks are executed this one executes too and with it, it will loop through all the C callbacks and executes them one by one.
For example in my case, the callbacks needed to be run in a Python module, so in my constructor I had to do something like this:
CORE_API Core::Core(LogFunction logInfo)
{
//....
// add our 'Callback delegate' to the list of callbacks
// that would run.
callbackPyList.attr("append")(py::cpp_function([this](bool status, std::string id, py::array_t<uint8_t>& img)
{
this->DelegateCCallback(status, id, img);
}));
//...
}
You can get fancy with this and incorporate threads, etc as you wish.

Alternative to Inner Classes in C++

Let's say I am writing a "Device Tree Blob" for the bcm2835 RPi chip but in C++ files, rather then .dts files. The intent is to practice C++ and OS concepts.
I would like to be able to encapsulate not just register addresses, but functions which access those, and expose only top level uses as API functions.
In C++ this could be inner classes, to one big BCM2835 class like so:
//bcm2835.h
class BMC2835 : public ARMCpu
{
public:
void ACKLedOn(void);
void ACKLdOff(void);
void ACKLedBlink(void);
// I2C write to device (this would be called by the device driver)
// It would ensure that I2C is setup, etc, etc
void I2C_Device_Write(I2C_Device* device, uint8_t* buffer);
private:
// Physical addresses for various peripheral register sets
/// Base Physical Address of the BCM 2835 peripheral registers
const uint32_t BCM2835_PERI_BASE = 0x20000000;
class GPIO()
{
private:
/// Base Physical Address of the Pads registers
const uint32_t BCM2835_GPIO_PADS = (BCM2835_PERI_BASE + 0x100000)
/// Sets the Function Select register for the given pin, which configures
/// the pin as Input, Output or one of the 6 alternate functions.
void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode);
}
class I2C()
{
private:
const uint32_t BCM2835_CORE_CLK_HZ = 250000000 ;///< 250 MHz
// Register masks for BSC_C
const uint32_t BCM2835_BSC_C_I2CEN = 0x00008000;///< I2C Enable, 0 = disabled, 1 = enabled
const uint32_t BCM2835_BSC_C_INTR = 0x00000400;///< Interrupt on RX
const uint32_t BCM2835_BSC_C_INTT = 0x00000200;///< Interrupt on TX
void bcm2835_i2c_begin(void);
void bcm2835_i2c_write(uint8_t address, uint8* pbuffer);
}
}
And then I can also have a class for the BCM2837 which is 64-bit and handles the LED very differently for example.
//bcm2837.h
class BCM2837 : public ARMCpu
{
public:
// LED is now a very different Implementation with Mailbox
// but exposed to Kernel as API
void ACKLedOn(void);
void ACKLdOff(void);
void ACKLedBlink(void);
...
...
}
I am sure there many problems with this approach. The one that seems to bother me the most is the length of the single class after you include things like SPI, UART, etc, etc.
Even if the ARMCpu is well desigend and 100% virtual (which I would rather avoid in embedded), each CPU class will still be rather lengthy and difficult to read and maintain.
Is there a way to achieve this type of private level access in C++ which is easier?
Put each chip in its own .cpp file, and declare all those private, internal things within that file (and not in the header). You can wrap them in anonymous namespace to keep them from being exposed to the linker.

Avoid creating multiple copies of code in memory

I'm new to developing on embedded systems and am not used to having very little program memory (16kB in this case) to play with. I would like to be able to create global variables, arrays, and functions that I can access from anywhere in the program while only existing in one place in memory. My current approach is to use static class members and methods that I can use by simply including the header file (e.g. #include "spi.h").
What is the best approach for what I'm trying to do?
Here is an example class. From what I understand, variables such as _callback and function definitions like call() in the .cpp will only appear in spi.o so they will appear only once in memory, but I may be mixed up.
spi.h:
#ifndef SPI_H_
#define SPI_H_
#include "msp430g2553.h"
class SPI {
public:
typedef void (*voidCallback)(void);
static voidCallback _callback;
static char largeArray[1000];
static __interrupt void USCIA0TX_ISR();
static void call();
static void configure();
static void transmitByte(unsigned char byte, voidCallback callback);
};
#endif /* SPI_H_ */
spi.cpp:
#include "spi.h"
SPI::voidCallback SPI::_callback = 0;
char SPI::largeArray[] = /* data */ ;
void SPI::configure() {
UCA0MCTL = 0;
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0TXIE;
}
void SPI::transmitByte(unsigned char byte, voidCallback callback) {
_callback = callback;
UCA0TXBUF = byte;
}
void SPI::call() {
SPI::_callback();
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void SPI::USCIA0TX_ISR()
{
volatile unsigned int i;
while (UCA0STAT & UCBUSY);
SPI::call();
}
The data members and the member functions of the class you wrote will only be defined once in memory. And if they're not marked static, the member functions will still only be defined once in memory. Non-static data members will be created in memory once for each object that you create, so if you only create one SPI object you only get one copy of its non-static data members. Short version: you're solving a non-problem.
As per Pete, static won't affect code doubling up, only member vars. In your example, there is 0 difference between static non static memory usage except perhaps for the _callback var (which you call out as an error.) And that one variable would only double up if the class were created more than once.
If you want code to not exist in memory when not in use, look into overlays or some sort of dynamic linking process. DLL type code will probably be major overkill for 16K, but overlays with compressed code might help you out.
Also, beware of extra linked in code from libraries. Closely examine your .map files for code bloat from innocuous function calls. For instance, a single printf() call will link in all sorts of vargs stuff if it is the only thing using it. Same for software floating point (if you don't have a FP unit by default.)

Plain C callback function pointer as part of iPhone delegate protocol?

Trying to integrate plain C/C++ code into iPhone project as an external static library. So far so good, but now I'm stuck at a point, where I need to register library callbacks. The library should notify my iPhone application, when something happens. Seems like a good place to define a Delegate.
...but the library is expecting C function pointers for callbacks. How do I define those in Objective-C, how do I use those as part of delegate pattern?
Sorry, really can't give sample code. Here's something bit similar: first interface I got to use to register, followed by definitions of callbacks.
registerCallBack(&aCBack, &bCBack, &cCBack, &dCBack, &eCBack);
typedef void (aCBack)(uint32_t magic);
typedef void (bCBack)(const NewData* newData);
typedef void (cCBack)(uint32_t value, const std::vector<DataStuff*>* stuff);
typedef void (dCBack)(uint32_t value, const SomeData* data, const std::string text, uint32_t type);
typedef void (eCBack)(uint32_t value, const MoreData* more);
...oh btw, one of the problems is that each Objective-C class method has two hidden arguments. Not sure how to deal with that at all. Besides changing interface of that external library.
You need to use C++/C interfaces for the callbacks which then internally delegate the call to your Objective-C code. Where the callback registrations allow you to pass in user-data of sufficient size, you can conveniently pass something that identifies your context like in this answer.
Callbacks that don't get passed any context have to call a class method of your Objective-C part anyway.
You have to use plain C functions for this, but you can call through to your delegate object from them as long as you're compiling as Objective-C:
// need to have a reference to the object, of course
static DelegateClass* delegate = NULL;
// call at runtime with your actual delegate
void setCallbackDelegate ( DelegateClass* del ) { delegate = del; }
void callbackA ( uint32_t magic )
{
[delegate handleCallbackA:magic];
}
// and so on...
[Update: as gf points out, you can use a class method and avoid the need for setCallbackDelegate.]