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.
Related
I'm building up a static embedded C-library, which has an API header file, that lists all available functions. I am not sure about a few thing, that I would like to clarify first before I start implementing it.
First of all, since this is a C-Library for embedded systems, which has hardware FPU, I'm not sure what I should include to calculate the math functions like sinf() etc. Normally I use the hardware specific includes, but that is not avialable in this static C-library, since it can run on some STM32 or even some AVR etc. How can I solve this problem?
Further Lets say I have the files foo.c and foo.h, which provide some hidden functions in the library and then there is the api.h, which can be seen by a user and api.c, which is also hidden. In foo.h are now some structs defined, that I would like to return in a callback to a user. Since this structs are hidden, I'm not sure how I should handle this callbacks. Should I implement a handler in api.c, which maps the structs from the callback from foo.c and pass them to the users callback, where the structs are redefined (with different name) in api.h or are there solutions with less overhead?
When I would define the necessary structs for foo.h in api.h, I would need to include api.h in foo.h, but also foo.h in api.h, that is not a good idea I think.
For the first part of the question, the mathematical operations like sinf should be handled by the C standard library (you should check you specific version for support on your architecture). You can then use the math.h header and its functions, the compiler should then use the FPU to make the floating point computations.
For the second part, the usual way to show the user a hidden structure is with a foward declaration but the user will have to interact with the structure through pointers and access functions.
With you example, say we have four files:
api.h: public header
api.c: source code for functions from the public header
foo.h: library internal header (will not be shipped to the end-user)
foo.c: source code for the internal functions
The api.h is the only interesting file of those (have no changes).
// file: api.h
#ifndef API_H
#define API_H
struct foo; // forward declaration of the foo structure
typedef void (*callback_t)(struct foo*); // typedef for a callback taking a
// struct foo argument
void set_callback(callback_t fn);
#endif
Now we have a type for the callback and the type of the structure given to the callback, but the user cannot interact with the structure itself, since the compiler only knows it exists but does not know its content (nor storage size).
When the user writes a callback like in the below code, the user will need to have some access functions.
#include "api.h"
void user_callback(struct foo* arg) {
// user code here
}
The access functions are usually defined like this:
// in the file api.h or another header that the user has access to
int foo_get_value1(struct foo* arg);
void foo_set_value1(struct foo* arg, int new_value);
and those functions would be implemented in foo.c
struct foo {
int value1;
int value2;
};
int foo_get_value1(struct foo* arg) {
return arg->value1;
}
void foo_set_value1(struct foo* arg, int new_value) {
arg->value1 = new_value;
}
This approach has the added advantage that your foo_set functions can do validity checks to make sure you have appropriate values in your structure.
Please note: I did not add any checks to my access functions to avoid cluttering the code, but when passing a pointer to a function, you should always check it for NULL
Is there is a way to implement access specifiers like "private", "protected" in C language. I came across solutions in the internet about using "static" and "ifdefs" for making a function available only inside certain other functions.
Apart from these, is there any C implementation equivalent of using private and protected access specifiers in C++ classes?
C does not have access specifiers. The only way to hide something from your callers is to not provide its declaration in the header.
You can make it static in the translation unit:
myapi.h
extern int visibleVariable;
void visibleFunction();
myapi.c
int visibleVariable;
static int invisibleVariable;
void visibleFunction() {
...
}
static void invisibleFunction() {
...
}
You can also hide the definition of a struct by placing it in the implementation file. This way all fields of your struct would be private to the translation unit. The drawback to this approach is that the users of your API would be unable to declare variables of your struct's type, so they would need to deal with your struct through pointers.
C has no concept of inheritance, hence there is no equivalent of protected access.
C does not have user definable name spaces or access specifiers. Since you exclude (ab)use of preprocessor, the only way to get compiler error trying to access private parts of "classes" is to not have a .h file which exposes "private" stuff. They can still be put into "private" separate .h files (included by module's or library's own .c files, but not meant to be included from application code), or hidden behind #ifdefs (requiring special define to activate the "private" parts).
One common way to hide things is to use opaque structs AKA opaque pointers. For that approach, the code outside a module or library only has pointer to a struct, but no struct definition. And then it uses functions offered by the module to get an instance, access it, and finally release it.
With this approach, you easily get public interface: the functions you provide in the public .h file, as well as any public support structs which have definition there. The private interface is the code where the full struct definition is visible, and any functions which are not in the public .h file.
Protected access implies inheritance, which usually works very differently from C++, when implemented with C by hand, and which is too broad a subject to cover in this answer. The closest thing to this would probably be to have several .h files, which provide several levels of "public" access, and then it is responsibility of the programmer to not get into problems with them.
The good thing about this approach is, other code using the module does not need to be modified (or even recompiled), if struct is changed. Often struct might even be an union, and then the module's functions would branch based on the actual type, all invisibe from the code using it. Another good thing is, the module can control creation of structs, so it could for example have a pool of structs and avoid using heap, all invisible to the application code. One downside is, you can't have inline functions (because the inline function body in .h file would need the struct definition, which we are trying to hide here), which prevents some nice compiler optimizations in cases where performance is a concern.
Example (untested code written for this answer):
module.h:
// ...other standard header file stuff ...
// forward declaration of struct
struct module_data;
// "constructor" function
struct module_data *module_initialize_data(int value);
// modification function
int module_update_data(struct module_data *data, int adjust);
// "destructor" function
void module_release(struct module_data *data);
module.c
#include "module.h"
// struct definition only in the .c file
struct module_data {
int value;
};
struct module_data *module_initialize_data(int value) {
struct module_data *data = malloc(sizeof(*data));
data->value = value;
return data;
}
int module_update_data(struct module_data *data, int adjust) {
data->value += adjust;
return data->value;
}
void module_release(struct module_data *data) {
free(data);
}
Relevant Wikipedia links for reference:
https://en.wikipedia.org/wiki/Opaque_pointer
https://en.wikipedia.org/wiki/Opaque_data_type
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.
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 *, ...);
Is there any standardized structure of C source and header files?
I'm thinking about something like this (example for C source file):
// static variables
// public variables
// static methods
// public methods
This is a totally subjective question. However, here's what I do approximately.
Header:
// extern defines, constants and enums
// public types
// extern methods
There are no extern variables :-)
Compilation unit:
// includes
// definitions for extern constants
// static function prototypes
// everything else
I tend to group things that are related together, so I don't rigidly put all of the static variables or defines in oner place, but near where they are going to be used.
Given that this is a C question, I presume:
// static variables
// public variables
// static methods
// public methods
... means:
// static variables
// public variables (external linkage)
// static functions
// public functions
As for the order, I don't think you can evoke anything but a subjective response about this. It is certainly not standardized unless you are asking about a specific organization's coding standards, in which case they might have policies about this. Some might prefer privates before publics, others publics before privates. Some might put one before the other to emphasize the importance of one over the other, while others might put it after to emphasize the important over its predecessor. There's no unanimous agreement about these kinds of stylistic preferences and they have no logical effect on the code or its runtime behavior.
The important thing is to be consistent and I'd recommend avoiding anything very exotic as it will scare away other developers who have to look at your code. Exotic styles are usually bad if you want to work with other engineers. The more exotic styles become, the more uniquely personal they are the more they demand of others to adjust to personal preferences.
Do try to cut down on the number of public variables with external linkage (global variables). As small a difference as it sounds, it's a big step up to write a public function to fetch a variable, even if it's simple getter-type function which returns a pointer to the variable, as it'll at least allow you to modify that code if a change ever becomes necessary and also allow you to easily put breakpoints wherever it is accessed, add instrumentation to the function, etc.
I usually use the following for c:
// include guard
#ifndef <filename>_H
#define <filename>_H
// define this as extern for c++
#ifdef __cplusplus
extern "C" {
#endif
#include <libraries>
#define <preproc variables>
#define <preproc macros>
enum <enums> {
};
typedef <variables>;
typedef <structs>;
function prototypes();
// end c++ guard
#ifdef __cplusplus
}
#endif
// end include guard
#endif
The structure you are using is good.
Best practice is with regards to naming the public variables and public methods, prefix the same with the product's name / company's name to avoid naming conflict with other libraries.