I wrote some code that uses function pointers to link modules functions in c. I was wondering is it possible to use those function pointers to access state in another translation unit.
I wrote this struct to handle life cycle functions so that I can have a module doing everything, you pass in a pointer to this struct with your functions and they get called when they are suppose to.
typedef struct {
void (*init_func_ptr)(void);
void (*fixed_update_func_ptr)(void);
void (*variable_update_func_ptr)(double alpha);
void (*variable_render_func_ptr)(double alpha);
void (*pause_func_ptr)(void);
void (*resume_func_ptr)(void);
void (*resize_func_ptr)(int width, int height);
void (*handle_event_func_ptr)(key_event *e);
void (*quit_func_ptr)(void);
} lifecycle_ptrs;
i typically set it up like this
lifecycle_ptrs* ptrs;
ptrs = calloc(1, sizeof(lifecycle_ptrs));
ptrs->init_func_ptr = &init;
ptrs->fixed_update_func_ptr = &fixed_update;
ptrs->variable_update_func_ptr = &variable_update;
ptrs->variable_render_func_ptr = &variable_render;
ptrs->pause_func_ptr = &pause;
ptrs->resume_func_ptr = &resume;
ptrs->resize_func_ptr = &resize;
ptrs->handle_event_func_ptr = &handle_events;
ptrs->quit_func_ptr = &quit;
this ptrs struct is setup in the module that defines main and is passed as a function argument. Once this is passed the program goes into an infinite loop until the user requests to quit.
So far this works pretty well and does what I want to do.
What I was curious about now is, is it possible to have something like this where I am able to access variables from the other module?
Let's say module a looks like this
modulea.c
int a;
int b;
char t[] = "test";
moudleb.c
struct t;
float 12.0;
is it possible to access module a's member variables from moduleb or visa versa?
I could write functions to get each thing but I feel there might be more elegant and maintainable way to do that. I could also define a struct and do a swap function where module a get access to the variables in module b and visa versa but again this seems a bit odd to me.
Are there any other ways to do this? I am more concerned about maintainability but any insights would help because right now I am at a loss.
Yes, technically it is possible, simply use extern.
However, there is no reason why you should ever do that. If you ever come up with a need to access (non-constant) variables in another file, then that means that your program design is broken.
And if you go through with extern, it will become even more broken, you'll get complete spaghetti code with very tight coupling, where everything in the program depends on everything else and all bugs will fail-escalate through the program and tear down things completely unrelated to the bug.
So the proper solution is to step back and think twice about the overall program design.
Instead of such spaghetti-coding, use object-oriented design and write each h and c file pair so that they together form an autonomous module (call it class, ADT or what you will), which is only concerned with it's own designated purpose. All file scope variables inside such a c file should be declared static to block access from outside. Access to such variables, if at all needed, should be done through setter/getter functions. The only kind of variables that is acceptable to share directly across files are read-only constants.
Though note that you should avoid file scope variables as far as possible, as they will make the code non-reentrant.
Easiest way to share members between different c modules is to use headers files.
You could add a modulea.h file to your project like:
#ifndef modulea_H_
#define modulea_H_
extern int a;
extern int b;
extern char t[];
#endif
Then you can #include "modulea.h" in your moduleb.c source file.
Related
I have a struct that needs to keep track of how many instances of this struct there are. Is there any way to do it within the struct, or do I have to make a separate counter outside the struct and increment this?
Thanks
To do this you would need a static variable but in C a struct is not allowed to have static variables (while in C++ you can, since they're basically classes). Especially because there are no namespaces so it wouldn't make any difference to have it declared inside a struct definition.
You are allowed to have global static variables though, which could be the simpler solution if you don't want to expose anything, something like:
//header.h
void incrementCounter();
void decrementCount();
int counterValue();
//header.c
static int counter = 0;
void incrementCounter() { ++counter; }
..
Nothing in the C language keeps track of when structures are created and destroyed. Indeed, when functions like malloc() are used to reserve memory for structures, the compiler has no way of knowing what structures "exist". This is different from Java or C++, where the only way an object can come into existence is by asking the code for the object to create an instance. Incidentally, in .NET, class objects are generally only brought into existence via request to the underlying class, but structures--as in C--can be brought into existence without any of the code associated with the structure knowing about it.
I've looked long and hard into this topic of avoiding global variables and have come up with a way of doing it that I haven't really seen anywhere else in my searches which leads me to believe it's maybe not a great way of doing it (or I'm just not wording my search correctly).
As an example I have something like this:
int16_t DataProcessing(uint8_t CallType, struct DataStruct *DataIO)
{
int16_t RetVal;
static struct DataStruct StaticDataStuct;
switch (CallType)
{
case FIRSTCASE: RetVal = FirstCaseProcessing(&StaticDataStuct,DataIO); break;
case SECONDCASE: RetVal = SecondCaseProcessing(&StaticDataStuct,DataIO); break;
...
etc
...
}
return RetVal;
}
int16_t FirstCaseProcessing(struct DataStruct *StaticData, struct DataStruct *NewData)
{
// Do what you need to do here
}
Same idea for any other routines that are called.
I have also done wrapper functions to call DataProcessing() that makes the whole thing much easier to read and for new people using it in the future. So, for example:
int16_t FirstCase(uint8_t Address, uint16_t Data)
{
struct DataStruct NewData;
NewData.Address = Address;
NewData.Data= Data;
return DataProcessing(FIRSTCASE, &NewData);
}
So, what seems good, is that other than for the interrupts such as UART and timers, I have no global variables at all. (I still think getting in and out of interrupts as fast as possible is better than having an interrupt call something to store data in a static variable somewhere, but am happy to be persuaded otherwise.)
What is [maybe] bad is that I'm passing stuff through three functions in the interests of avoiding globals and making it more readable (assuming it's not just me that finds it readable!)
I would say that I have been given a 72MHz embedded 32 bit processor to do what could be done with an eight bit processor, running at a fraction of the speed (assuming it had enough RAM). So speed is not an issue, although I'm interested in opinions on whether this is a good style for when speed might be more of an issue.
I've seen the C++ style of having .c files and having static variables that any function within that .c file can see and access (but external files cannot), passing values/pointers etc in and out with accessor functions, but they seem to use what I would think are variables that are "global" to the file (or local to the file depending how you want to look at it!). Also, it's possible to have one function that stores a static variable and simply passes a pointer to that static variable to anything that wants to access it. I'm wondering whether that would be going OTT?
Does my idea seem good/bad/terrible?
Many thanks for any advice and all the TL;DRs I'm probably going to get. ;~)
OP:Does my idea seem good/bad/terrible?
Good OP is not yet OTT.
Avoiding global variables in embedded designs is a good goal primarily for the sake of maintenance. Information hiding (making data local to a function or object) is key to controlling the myriad of interactions and making debugging easier. This is especially true with OP faster (and likely larger memory) processor.
An alternative - hide data in file scope.
OP solution appears hierarchical as at DataProcessing(), command and Input/Output parameters are given and details of DataStruc are known at this level.
I'm aim for more of a data driven approach, using a pointer or index and a set of routines. Say in an embedded program I need, at most, Sally_N instances of a Sally variable. Here my data is not global, but hidden in the file scope of Sally.c. Thus the data and its detailed fields are hidden far from the higher level code that uses it. In OP's approach, the details of DataStruct are known to the higher level function DataProcessing().
// Sally.h
struct Sally_t; // Does not expose the fields
extern struct Sally_t *Sally_Init(...);
extern void Sally_DoThis(struct Sally_t *, ...);
extern void Sally_DoThat(struct Sally_t *, ...);
// Sally.c
struct Sally_t { int a, ... }; // Structure details
static struct Sally_t Sally_Data[Sally_N];// file scope prevents global exposure
struct Sally_t *Sally_Init(...);
void Sally_DoThis(struct Sally_t *, ...);
void Sally_DoThat(struct Sally_t *, ...);
I'm going round and round in circles trying to work out how to implement variables that need to be accessed by multiple functions within a [.c] file.
I have been ploughing through thread after thread on Stack Exchange and other Google searches where the general [but certainly not unanimous] consensus seems to be that file-wide static variables are fine, yet, you should pass variables (or at the very least pointers to variables) into functions and not just have any old function access the static file-wide variable (i.e. one that is declared outside of any function). Some people have said file-wide statics are essentially as bad as globals, but give no indication of how to avoid globals if not with file-wide statics!
However, at some point, even if you pass pointers to the file-wide static variable from function to function, some function has to originally access that file-wide static variable. Also, I cannot see a way where just one function within the .c file can be the sole function that accesses that static variable, because not all functions that will need the static variable would go through one single function.
It seems to me that you could have a function that does nothing but holds a static variable and returns a pointer to that static variable. Any function that needs to access that variable calls that function, gets the pointer to the variable and does what it needs to do with the variable. This kind of thing:
struct PacketStruct* GetPacketStructPtr(void)
{
static struct PacketStruct Packet;
return &Packet;
}
I've seen some people here say, yep, that's how a singleton factory is built (whatever that is) and it's completely valid, yet others say it's dangerous (but without really explaining why it's dangerous), others have said it's poor practice (I think they said it was inefficient, but I've read so much today I could be wrong).
So, what I am trying to ascertain is this:
Are file wide variables OK?
If so, given that it seems so wrong just to have all functions access that file-wide static variable and not pass pointers to it [the static file-wide variable] - as much as anything to make function re-use with different variables possible - can you just decide the first function that needs to access the file-wide static does so and then passes pointers all the way down to other functions? I really hate the look of code that just access the file-wide static variable, even though it also seems a little daft passing a pointer to something that the function can access anyway.
If file-wide static variables are not valid, given that this is not multi-threaded and just a run-to-complete program on an embedded micro, can/should I use that way of passing a pointer to the function-wide static variable to any other function that needs access to the variable?
If none of the above, how on earth do you avoid the dreaded global variables? This question of not using globals seems to have been tackled a zillion times here but without any concrete examples of how to do it. There is an awful lot of contradictory advice knocking about here, let alone on the rest of the web!
I stress this is single thread, not re-entrant and all relatively simple.
Hopefully, this gives some more idea about what I'm trying to do:
#include "work_order.h
// This is work_order.c
// Nothing outside of this file needs to access the WorkOrder struct
static struct WorkOrderStruct WorkOrder;
// Package up a work order - *data is a pointer to a complete serial package
int16_t CableConnectOrder(uint8_t *Data)
{
if (UnpackagePortInformation(&WorkOrder.PortA,&Data) == CARD_UID_NOT_FOUND)
return CARD_UID_NOT_FOUND;
if (UnpackagePortInformation(&WorkOrder.PortB,&Data) == CARD_UID_NOT_FOUND)
return CARD_UID_NOT_FOUND;
AddNewKeysToWorkOrder(&WorkOrder,Data);
WorkOrder.WorkOrderType = CONNECT_CABLE_REQUEST;
WorkOrder.Flags.SingleEndedConnection = FALSE_BIT;
WorkOrder.Flags.PortACableRemoveRequest = FALSE;
WorkOrder.Flags.PortBCableRemoveRequest = FALSE;
return ConstructCableOrderRequest(&WorkOrder);
}
int16_t ConstructCableOrderRequest(struct WorkOrderStruct *WorkOrder)
{
// This function is accessed by other Work Order requests and does the rest of the // packaging of the work order
// It can also pass the work order information further down
DoOtherStuff(WorkOrder); // Kind of further passing that might happen
}
int16_t CheckAdditionalInfoAgainstWorkOrder(struct WorkOrderPortUpdateStruct *Update)
{
// Compare connection information against the previously set-up work order
// Needs to access the static WorkOrder structure as well. Also, can call other
// functions that needs to access the static function
WorkOrder.Foo = Update->bar;
DoYetMoreOtherStuff(&WorkOrder); // This is not real code, but the general kind of idea
}
More information on what you're doing would be helpful. I often do embedded system programming where globals/file-wide statics are an absolute must due to interrupts. If that is what you're working on - go for it.
Re: A single function that creates the variable and passes a pointer to all other functions...
Your "single function" would be main. I'll often create code like so...
struct PacketStruct {
char name[128];
uint8_t age;
float bac;
}
void setup (PacketStruct *packetStruct, ...);
void foo (PacketStruct *parameter);
void bar (PacketStruct *parameter);
int main (void) {
PacketStruct ps;
// Initialize all variables"
setup(&ps);
// Run program
foo(&ps);
bar(&ps);
return 0;
}
void setup (PacketStruct *packetStruct, ...) {
strcpy(packetStruct->name, "Squidward");
packetStruct->age = 16;
packetStruct->bac = 0.11;
}
I like this because ps is not a global variable, you do not have to dynamically allocate memory (though you could just as easily do so), and it becomes accessible in all functions.
Again, if you post your full code (or a snippet showing how it's used) we might be able to give you some applications specific advice.
-Edit-
Since you're mentioning file-wide, I'm guessing that means you're not using this variable in the same file as main. In that case, my sub-files will have functions like filename_init(...)...
/* File: FooBar.c
*/
#include "FileWithPacketStructAndOtherCoolThings.h"
// "g_" sits in front of all global variables
// "FooBar_" sits in front of all file-wide statics
static PacketStruct g_FooBar_ps;
FooBar_init(void) {
strcpy(g_ps->name, "Squidward");
g_ps->age = 16;
g_ps->bac = 0.11;
}
I would like to give a module variable a read-only access for client modules.
Several solutions:
1. The most common one:
// module_a.c
static int a;
int get_a(void)
{
return a;
}
// module_a.h
int get_a(void);
This makes one function per variable to share, one function call (I am thinking both execution time and readability), and one copy for every read. Assuming no optimizing linker.
2. Another solution:
// module_a.c
static int _a;
const int * const a = &_a;
// module_a.h
extern const int * const a;
// client_module.c
int read_variable = *a;
*a = 5; // error: variable is read-only
I like that, besides the fact that the client needs to read the content of a pointer. Also, every read-only variable needs its extern const pointer to const.
3. A third solution, inspired by the second one, is to hide the variables behind a struct and an extern pointer to struct. The notation module_name->a is more readable in the client module, in my opinion.
4. I could create an inline definition for the get_a(void) function. It would still look like a function call in the client module, but the optimization should take place.
My questions:
Is there a best way to make variables modified in a module accessible as read-only in other modules? Best in what aspect?
Which solutions above would you accept or refuse to use, and why?
I am aware that this is microoptimization - I might not implement it - but I am still interested in the possibility, and above all in the knowing.
Concerning option #4, I'm not sure you can make it inline if the variable isn't accessible outside the implementation file. I wouldn't count options #2 and #3 as truly read-only. The pointer can have the constness cast away and be modified (const is just a compiler "warning", nothing concrete). Only option #1 is read-only because it returns a copy.
For speed identical to variable access, you can define an extern variable inside an inline function:
static inline int get_a(void)
{
extern int a_var;
return a_var;
}
This is simple and clear to read. The other options seem unnecessarily convoluted.
Edit: I'm assuming that you use prefixes for your names, since you write C. So it will actually be:
extern int my_project_a;
This prevents a client from accidentally making a variable with the same name. However, what if a client makes a variable with the same name on purpose? In this situation, you have already lost, because the client is either 1) actively trying to sabotage your library or 2) incompetent beyond reasonable accommodation. In situation #1, there is nothing you can do to stop the programmer. In situation #2, the program will be broken anyway.
Try running nm /lib/libc.so or equivalent on your system. You'll see that most libc implementations have several variables that are not defined in header files. On my system this includes things like __host_byaddr_cache. It's not the responsibility of the C library implementors to babysit me and prevent me from running:
extern void *__host_byaddr_cache;
__host_byaddr_cache = NULL;
If you start down the path of thinking that you have to force clients to treat your variable as read-only, you are heading down the path of fruitless paranoia. The static keyword is really just a convenience to keep objects out of the global namespace, it is not and never was a security measure to prevent external access.
The only way to enforce read-only variables is to manage the client code — either by sandboxing it in a VM or by algorithmically verifying that it can't modify your variable.
The most common one:
There's a reason why it's the most common one. It's the best one.
I don't regard the performance hit to be significant enough to be worth worrying about in most situations.
I'm making a little game in C. I try to program in an object-oriented manner using function pointers.
I really wanted to push ahead this time and not overdo making things too generic, I often get lost in this. Using plain old C has helped me a lot in programming faster and better.
Currently, I describe "Game states" using:
/* macros */
#define SETUP_ROUTINE(component) component##_##setup_routine
#define DRAW_ROUTINE(component) component##_##draw_routine
#define EVENT_ROUTINE(component) component##_##event_routine
#define UPDATE_ROUTINE(component) component##_##update_routine
#define TEARDOWN_ROUTINE(component) component##_##teardown_routine
#define SETUP_ROUTINE_SIGNATURE void
#define DRAW_ROUTINE_SIGNATURE void
#define EVENT_ROUTINE_SIGNATURE SDL_Event evt, int * quit
#define UPDATE_ROUTINE_SIGNATURE double t, float dt
#define TEARDOWN_ROUTINE_SIGNATURE void
/* data */
typedef enum GameStateType {
GAME_STATE_MENU,
GAME_STATE_LEVELSELECT,
...
} GameStateType;
typedef struct GameState {
GameStateType state;
GameStateType nextState;
GameStateType prevState;
void (*setup_routine)(SETUP_ROUTINE_SIGNATURE);
void (*draw_routine)(DRAW_ROUTINE_SIGNATURE);
void (*event_routine)(EVENT_ROUTINE_SIGNATURE);
void (*update_routine)(UPDATE_ROUTINE_SIGNATURE);
void (*teardown_routine)(TEARDOWN_ROUTINE_SIGNATURE);
} GameState;
While you may or may not appreciate this style, I have grown to like it and it serves me well so far on this small (private..) project.
I for instance have a "transition" game state that simply transitions from one game state to the other.
However, when I link the different game states together, I get ugly things like:
extern GameState GAME; /* The 'singleton' "game" */
extern void menu_setup_routine(SETUP_ROUTINE_SIGNATURE);
extern void menu_draw_routine(DRAW_ROUTINE_SIGNATURE);
extern void menu_event_routine(EVENT_ROUTINE_SIGNATURE);
extern void menu_update_routine(UPDATE_ROUTINE_SIGNATURE);
extern void menu_teardown_routine(TEARDOWN_ROUTINE_SIGNATURE);
extern void debug_setup_routine(SETUP_ROUTINE_SIGNATURE);
extern void debug_draw_routine(DRAW_ROUTINE_SIGNATURE);
extern void debug_event_routine(EVENT_ROUTINE_SIGNATURE);
extern void debug_update_routine(UPDATE_ROUTINE_SIGNATURE);
extern void debug_teardown_routine(TEARDOWN_ROUTINE_SIGNATURE);
Also, for each game state I have things like:
menu.c
struct MenuModel menu_model; /* The singleton 'menu' model */
game.c
struct GameModel game_model; /* The singleton 'game' model */
..which are global pieces of data that remain on the heap throughout the execution of the program. Of course the fields of these usually consist of pointers to dynamic memory, which and which contents' change as the game states change.
While at first I thought this was insane I started to like it. However it may cause namespace conflicts when another .o is linked that also has such a "menu_model" symbol.
First question: is this insane, is there a better way of doing things like this? What do people usually do to avoid these possible symbol name conflicts?
Second question is that I have to republish the different ..._setup_routine/..draw_routine/.. functions using "extern.." in the one source file/object file that holds the following types of functions:
void (*get_setup_routine(GameStateType state))(SETUP_ROUTINE_SIGNATURE) {
switch(state) {
case GAME_STATE_MENU:
return SETUP_ROUTINE(menu);
break;
case GAME_STATE_LEVELSELECT:
return SETUP_ROUTINE(level_select);
break;
default: /* ... */ break;
}
}
Because otherwise when compiling it does not know the symbol "menu_setup_routine".
Anyway, any advise is welcome, I'm a bit new to C and although I really like programming in it, I wonder if I'm using it right in this case.
Some non-small games use similar paradigm. The first example which pops into my mind is Neverball.
You might want to download its source code (its an OpenSource game) and see how they're doing.
Personally I think you should check C++. I used to use C only, also in the way you're doing, up to a some years ago; then I went crazy (mostly because of name clashes), and switching to C++ made me discover a new world. Anyway I understand you could want to avoid it for a number of reasons.
About objecst like your menu_model, whose name clashes with other menu_model in other C source files, you should just declare them as static:
static struct MenuModel menu_model; /* The singleton 'menu' model */
That menu_model will be visible in the C source file it's declared in (you won't be able to use it in other C source files, not even by externing it), and its name won't clash with other static variables with the same name declared in other C source files.
About the second issue there's not much to do. Functions and variables you use must be declared.
I'm a bit confused, but I don't think you should need all those menu_setup_routine and so on to have external linkage. Instead, define a struct game_vtable containing one function pointer for each routine, and then let each of "menu" and "debug" provide access to an instance of that struct. To call a function on a component, you do something like:
// vtable is a global symbol
component##_##vtable.setup
or
// vtable is acquired from a function
component##_##getvtableptr()->setup
or you can pass vtable pointers around as parameters, in place of your GameStateType, and maybe thereby get rid of some of your switch statements.
As for the globals - you don't provide a lot of detail, but the way to avoid a global Menu is to create one locally, at a high level, and then pass it around to anyone that needs it. If you decide that you prefer the global, you have to give it a unique name if it's going to be visible outside its TU.