Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Code Reviews

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

66%
+2 −0
Code Reviews Pattern / architecture for interfacing with components in C

I'm working on the architecture, where the assumption is to easily extend the options in the system and also to provide some kind of encapsulation (from the main we could only access the type1 / ty...

1 answer  ·  posted 2mo ago by patriko8520‭  ·  last activity 2mo ago by Lundin‭

Question c architecture
#2: Post edited by user avatar Lundin‭ · 2024-03-28T11:48:30Z (about 2 months ago)
  • In the beginning, thanks for your advice Lundin.
  • I'm working on the architecture, where the assumption is to easily extend the options in the system and also to provide some kind of encapsulation (from the main we could only access the type1 / type2 through interface).
  • It will be an embedded software system, where there will be e.g. the same end device, but different inputs (digital or analog). I want to use the same interface to get the signal, but it could be handled in different ways. Each functionality will have its implementation, but the final signal will be the same and will be handed over to the next function.
  • I'm wondering about declaring the pointers in type*.h and using them in type*.c in this way
  • type1.h
  • extern stType1 *type1_object;
  • Is it proper to variable declaration, definition and use in the function in this way? It compiles, but could it be used in that way?
  • type1.c
  • static stType1 memReservation;
  • stType1 *type1_object = &memReservation;
  • bool getOneType1()
  • {
  • return type1_object->internalOne;
  • }
  • Whole code below:
  • ```
  • interface.h
  • #ifndef _INTERFACE_H
  • #define _INTERFACE_H
  • #include <stdbool.h>
  • #include <stdint.h>
  • #define DIGITAL 0
  • #define ANALOG 1
  • typedef struct hwInterface hwInterface;
  • struct hwInterface
  • {
  • void (*cyclic)();
  • bool (*getOne)();
  • bool (*getTwo)();
  • };
  • // common interface
  • extern hwInterface *hwInterfaceX;
  • void init(uint8_t Type);
  • void initType1();
  • void initType2();
  • #endif
  • ```
  • ```
  • interface.c
  • #include "interface.h"
  • static hwInterface memReservation;
  • hwInterface *hwInterfaceX = &memReservation;
  • void init(uint8_t Type)
  • {
  • // program depend from parameter
  • if (Type == DIGITAL)
  • {
  • initType1();
  • }
  • else if (Type == ANALOG)
  • {
  • initType2();
  • }
  • }
  • ```
  • ```
  • type1.h
  • #include <stdio.h>
  • #include "interface.h"
  • typedef struct stType1
  • {
  • hwInterface interface;
  • bool internalOne;
  • bool internalTwo;
  • } stType1;
  • extern stType1 *type1_object;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType1();
  • bool getOneType1();
  • bool getTwoType1();
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type1Printer();
  • ```
  • ```
  • type1.c
  • #include "type1.h"
  • static stType1 memReservation;
  • stType1 *type1_object = &memReservation;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType1()
  • {
  • // Read digital inputs, some logic //
  • // write to own variables //
  • type1Printer();
  • }
  • bool getOneType1()
  • {
  • return type1_object->internalOne;
  • }
  • bool getTwoType1()
  • {
  • return type1_object->internalTwo;
  • }
  • //////////////////////////
  • // INITIALIZATION //
  • //////////////////////////
  • void initType1()
  • {
  • printf("Init Type1 function\n");
  • type1_object->interface.cyclic = &cyclicType1;
  • type1_object->interface.getOne = &getOneType1;
  • type1_object->interface.getTwo = &getTwoType1;
  • hwInterfaceX = (hwInterface*)type1_object;
  • type1_object->internalOne = false;
  • type1_object->internalTwo = true;
  • }
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type1Printer()
  • {
  • printf("Cyclic type1 own function\n");
  • }
  • ```
  • ```
  • type2.h
  • #include <stdio.h>
  • #include "interface.h"
  • typedef struct stType2
  • {
  • hwInterface interface;
  • bool internalOne;
  • bool internalTwo;
  • } stType2;
  • extern stType2 *type2_object;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType2();
  • bool getOneType2();
  • bool getTwoType2();
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type2Printer();
  • ```
  • ```
  • type2.c
  • #include "type2.h"
  • static stType2 memReservation;
  • stType2 *type2_object = &memReservation;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType2()
  • {
  • // Read digital inputs, some logic //
  • // write to own variables //
  • type2Printer();
  • }
  • bool getOneType2()
  • {
  • return type2_object->internalOne;
  • }
  • bool getTwoType2()
  • {
  • return type2_object->internalTwo;
  • }
  • //////////////////////////
  • // INITIALIZATION //
  • //////////////////////////
  • void initType2()
  • {
  • printf("Init Type2 function\n");
  • type2_object->interface.cyclic = &cyclicType2;
  • type2_object->interface.getOne = &getOneType2;
  • type2_object->interface.getTwo = &getTwoType2;
  • hwInterfaceX = (hwInterface*)type2_object;
  • type2_object->internalOne = true;
  • type2_object->internalTwo = false;
  • }
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type2Printer()
  • {
  • printf("Cyclic type2 own function\n");
  • }
  • ```
  • ```
  • main.c
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <stdbool.h>
  • #include "interface.h"
  • void display(bool input)
  • {
  • printf("%d\n", input);
  • }
  • int main()
  • {
  • uint8_t Type = DIGITAL;
  • //////////////////////
  • // READ PARAMETERS //
  • //////////////////////
  • printf("Choose type (0 - DIG, 1 - ANALOG): ");
  • scanf("%hhd", &Type);
  • // INITIALIZATION //
  • init(Type);
  • while(1)
  • {
  • /////////////////////////////////////////////////////
  • // cyclic - access posible only through interface //
  • /////////////////////////////////////////////////////
  • hwInterfaceX->cyclic();
  • // external block (display) reads footboards state from interface
  • display(hwInterfaceX->getOne());
  • display(hwInterfaceX->getTwo());
  • // some delay
  • for(volatile uint32_t i = 0; i < 700000000; i++);
  • }
  • return 0;
  • }
  • ```
  • I'm working on the architecture, where the assumption is to easily extend the options in the system and also to provide some kind of encapsulation (from the main we could only access the type1 / type2 through interface).
  • It will be an embedded software system, where there will be e.g. the same end device, but different inputs (digital or analog). I want to use the same interface to get the signal, but it could be handled in different ways. Each functionality will have its implementation, but the final signal will be the same and will be handed over to the next function.
  • I'm wondering about declaring the pointers in type*.h and using them in type*.c in this way
  • type1.h
  • extern stType1 *type1_object;
  • Is it proper to variable declaration, definition and use in the function in this way? It compiles, but could it be used in that way?
  • type1.c
  • static stType1 memReservation;
  • stType1 *type1_object = &memReservation;
  • bool getOneType1()
  • {
  • return type1_object->internalOne;
  • }
  • Whole code below:
  • ```
  • interface.h
  • #ifndef _INTERFACE_H
  • #define _INTERFACE_H
  • #include <stdbool.h>
  • #include <stdint.h>
  • #define DIGITAL 0
  • #define ANALOG 1
  • typedef struct hwInterface hwInterface;
  • struct hwInterface
  • {
  • void (*cyclic)();
  • bool (*getOne)();
  • bool (*getTwo)();
  • };
  • // common interface
  • extern hwInterface *hwInterfaceX;
  • void init(uint8_t Type);
  • void initType1();
  • void initType2();
  • #endif
  • ```
  • ```
  • interface.c
  • #include "interface.h"
  • static hwInterface memReservation;
  • hwInterface *hwInterfaceX = &memReservation;
  • void init(uint8_t Type)
  • {
  • // program depend from parameter
  • if (Type == DIGITAL)
  • {
  • initType1();
  • }
  • else if (Type == ANALOG)
  • {
  • initType2();
  • }
  • }
  • ```
  • ```
  • type1.h
  • #include <stdio.h>
  • #include "interface.h"
  • typedef struct stType1
  • {
  • hwInterface interface;
  • bool internalOne;
  • bool internalTwo;
  • } stType1;
  • extern stType1 *type1_object;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType1();
  • bool getOneType1();
  • bool getTwoType1();
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type1Printer();
  • ```
  • ```
  • type1.c
  • #include "type1.h"
  • static stType1 memReservation;
  • stType1 *type1_object = &memReservation;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType1()
  • {
  • // Read digital inputs, some logic //
  • // write to own variables //
  • type1Printer();
  • }
  • bool getOneType1()
  • {
  • return type1_object->internalOne;
  • }
  • bool getTwoType1()
  • {
  • return type1_object->internalTwo;
  • }
  • //////////////////////////
  • // INITIALIZATION //
  • //////////////////////////
  • void initType1()
  • {
  • printf("Init Type1 function\n");
  • type1_object->interface.cyclic = &cyclicType1;
  • type1_object->interface.getOne = &getOneType1;
  • type1_object->interface.getTwo = &getTwoType1;
  • hwInterfaceX = (hwInterface*)type1_object;
  • type1_object->internalOne = false;
  • type1_object->internalTwo = true;
  • }
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type1Printer()
  • {
  • printf("Cyclic type1 own function\n");
  • }
  • ```
  • ```
  • type2.h
  • #include <stdio.h>
  • #include "interface.h"
  • typedef struct stType2
  • {
  • hwInterface interface;
  • bool internalOne;
  • bool internalTwo;
  • } stType2;
  • extern stType2 *type2_object;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType2();
  • bool getOneType2();
  • bool getTwoType2();
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type2Printer();
  • ```
  • ```
  • type2.c
  • #include "type2.h"
  • static stType2 memReservation;
  • stType2 *type2_object = &memReservation;
  • /////////////////////////
  • // INTERFACE FUNCTIONS //
  • /////////////////////////
  • void cyclicType2()
  • {
  • // Read digital inputs, some logic //
  • // write to own variables //
  • type2Printer();
  • }
  • bool getOneType2()
  • {
  • return type2_object->internalOne;
  • }
  • bool getTwoType2()
  • {
  • return type2_object->internalTwo;
  • }
  • //////////////////////////
  • // INITIALIZATION //
  • //////////////////////////
  • void initType2()
  • {
  • printf("Init Type2 function\n");
  • type2_object->interface.cyclic = &cyclicType2;
  • type2_object->interface.getOne = &getOneType2;
  • type2_object->interface.getTwo = &getTwoType2;
  • hwInterfaceX = (hwInterface*)type2_object;
  • type2_object->internalOne = true;
  • type2_object->internalTwo = false;
  • }
  • ///////////////////////
  • // PRIVATE FUNCTIONS //
  • ///////////////////////
  • void type2Printer()
  • {
  • printf("Cyclic type2 own function\n");
  • }
  • ```
  • ```
  • main.c
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <stdbool.h>
  • #include "interface.h"
  • void display(bool input)
  • {
  • printf("%d\n", input);
  • }
  • int main()
  • {
  • uint8_t Type = DIGITAL;
  • //////////////////////
  • // READ PARAMETERS //
  • //////////////////////
  • printf("Choose type (0 - DIG, 1 - ANALOG): ");
  • scanf("%hhd", &Type);
  • // INITIALIZATION //
  • init(Type);
  • while(1)
  • {
  • /////////////////////////////////////////////////////
  • // cyclic - access posible only through interface //
  • /////////////////////////////////////////////////////
  • hwInterfaceX->cyclic();
  • // external block (display) reads footboards state from interface
  • display(hwInterfaceX->getOne());
  • display(hwInterfaceX->getTwo());
  • // some delay
  • for(volatile uint32_t i = 0; i < 700000000; i++);
  • }
  • return 0;
  • }
  • ```
#1: Initial revision by user avatar patriko8520‭ · 2024-03-28T09:51:15Z (about 2 months ago)
Pattern / architecture for interfacing with components in C
In the beginning, thanks for your advice Lundin.
I'm working on the architecture, where the assumption is to easily extend the options in the system and also to provide some kind of encapsulation (from the main we could only access the type1 / type2 through interface). 
It will be an embedded software system, where there will be e.g. the same end device, but different inputs (digital or analog). I want to use the same interface to get the signal, but it could be handled in different ways. Each functionality will have its implementation, but the final signal will be the same and will be handed over to the next function. 

I'm wondering about declaring the pointers in type*.h and using them in type*.c in this way 


    type1.h
    extern stType1 *type1_object;

Is it proper to variable declaration, definition and use in the function in this way? It compiles, but could it be used in that way?


    type1.c
    static stType1 memReservation;
    stType1 *type1_object = &memReservation;

    bool getOneType1()
    {
        return type1_object->internalOne;
    }

Whole code below:


```
interface.h

#ifndef _INTERFACE_H
#define _INTERFACE_H
#include <stdbool.h>
#include <stdint.h>

#define DIGITAL 0
#define ANALOG  1

typedef struct hwInterface hwInterface;

struct hwInterface
{
    void (*cyclic)();
    bool (*getOne)();
    bool (*getTwo)();
};

// common interface
extern hwInterface *hwInterfaceX;

void init(uint8_t Type);
void initType1();
void initType2();

#endif

```


```
interface.c

#include "interface.h"

static hwInterface memReservation;
hwInterface *hwInterfaceX = &memReservation;

void init(uint8_t Type)
{
    // program depend from parameter
    if (Type == DIGITAL)
    {
        initType1();
    }
    else if (Type == ANALOG)
    {
        initType2();
    }
}
```


```
type1.h

#include <stdio.h>
#include "interface.h"

typedef struct stType1
{
    hwInterface interface;
    bool internalOne;
    bool internalTwo;
} stType1;

extern stType1 *type1_object;

/////////////////////////
// INTERFACE FUNCTIONS //
/////////////////////////
void cyclicType1();
bool getOneType1();
bool getTwoType1();

///////////////////////
// PRIVATE FUNCTIONS //
///////////////////////
void type1Printer();

```


```
type1.c

#include "type1.h"

static stType1 memReservation;
stType1 *type1_object = &memReservation;

/////////////////////////
// INTERFACE FUNCTIONS //
/////////////////////////
void cyclicType1()
{
    // Read digital inputs, some logic  //
    // write to own variables           //
    type1Printer();
}

bool getOneType1()
{
    return type1_object->internalOne;
}

bool getTwoType1()
{
    return type1_object->internalTwo;
}

//////////////////////////
//   INITIALIZATION     //
//////////////////////////
void initType1()
{
    printf("Init Type1 function\n");
    type1_object->interface.cyclic = &cyclicType1;
    type1_object->interface.getOne = &getOneType1;
    type1_object->interface.getTwo = &getTwoType1;
    hwInterfaceX = (hwInterface*)type1_object;
    
    type1_object->internalOne = false;
    type1_object->internalTwo = true;
}

///////////////////////
// PRIVATE FUNCTIONS //
///////////////////////
void type1Printer()
{
    printf("Cyclic type1 own function\n");
}

```


```
type2.h

#include <stdio.h>
#include "interface.h"

typedef struct stType2
{
    hwInterface interface;
    bool internalOne;
    bool internalTwo;
} stType2;

extern stType2 *type2_object;

/////////////////////////
// INTERFACE FUNCTIONS //
/////////////////////////
void cyclicType2();
bool getOneType2();
bool getTwoType2();

///////////////////////
// PRIVATE FUNCTIONS //
///////////////////////
void type2Printer();

```


```
type2.c
#include "type2.h"

static stType2 memReservation;
stType2 *type2_object = &memReservation;

/////////////////////////
// INTERFACE FUNCTIONS //
/////////////////////////
void cyclicType2()
{
    // Read digital inputs, some logic  //
    // write to own variables           //
    type2Printer();
}

bool getOneType2()
{
    return type2_object->internalOne;
}

bool getTwoType2()
{
    return type2_object->internalTwo;
}

//////////////////////////
//   INITIALIZATION     //
//////////////////////////
void initType2()
{
    printf("Init Type2 function\n");
    type2_object->interface.cyclic = &cyclicType2;
    type2_object->interface.getOne = &getOneType2;
    type2_object->interface.getTwo = &getTwoType2;
    hwInterfaceX = (hwInterface*)type2_object;
    
    type2_object->internalOne = true;
    type2_object->internalTwo = false;
}

///////////////////////
// PRIVATE FUNCTIONS //
///////////////////////
void type2Printer()
{
    printf("Cyclic type2 own function\n");
}

```



```
main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "interface.h"


void display(bool input)
{
    printf("%d\n", input);
    
}

int main()
{
    uint8_t Type = DIGITAL;
    
    //////////////////////
    // READ PARAMETERS  //
    //////////////////////
    printf("Choose type (0 - DIG, 1 - ANALOG): ");
    scanf("%hhd", &Type);
    
    // INITIALIZATION //
    init(Type);
    
    while(1) 
    {
        /////////////////////////////////////////////////////
        // cyclic  - access posible only through interface //
        /////////////////////////////////////////////////////
        hwInterfaceX->cyclic();
        
        // external block (display) reads footboards state from interface
        display(hwInterfaceX->getOne());
        display(hwInterfaceX->getTwo());
        
        // some delay
        for(volatile uint32_t i = 0; i < 700000000; i++);
        
    }

    return 0;
}




```