Append item to opaque linked list handler in C - c

Im beggining with linked list in C, and I found some problems where (if I understood well) manipulate linked lists without knowing internal structre (fields)!
Is it possible to append/remove an item in a linked list without knowledge of it's internal structure(opaque) given a pointer to the linked list?
Edit (adding details).
So the problem is to create a set of functions to manipulate linked lists, given a handler on the linked list as a parameter which is declared in the follwoing way :
typedef struct list *handler;
so for example I created a function to create a linked list :
handler ListCreate()
{
handler list = (handler)malloc(sizeof(handler));
if(!list)
{
printf("can not allocate memory \n");
return NULL;
}
return list;
}
but when it comes to appending, Im just blocked and I thought it can't be done, but maybe I'm wrong.
So this is the prototype of the function :
int ListAppend(handler list, void *item)

I wanted to do something similar, but I had to figure it out myself. The idea is to make an opaque object interface, and then give access to attributes of the implementation file by casting using a switch statement. I'm doing it this way to follow the dependency inversion principle. All of the code is in a single file to show that it compiles, but the three comment lines //interface, //dependency, and //context can be broken into different files so you can try different implementations of the dependency file without having to change the interface file.
#include <stdlib.h>
#include <stdio.h>
//interface
typedef enum {
DEP1,
DEP2
} Type;
typedef struct Interface{
struct Interface* ptr;
void* data;
int (*getConcreteStuff)(struct Interface*, Type t);
} Interface;
//dependency
typedef struct {
int concreteStuff1;
} Dependency1;
typedef struct {
int concreteStuff2;
} Dependency2;
static int getConcreteStuff(Interface* interface, Type t) {
switch(t){
case DEP1:
return ((Dependency1*) interface->data)->concreteStuff1;
break;
case DEP2:
return ((Dependency2*) interface->data)->concreteStuff2;
break;
}
}
Interface Dependency1_new(Interface* ptr){
Dependency1* d = malloc(sizeof(*d));
d->concreteStuff1 = 1;
struct Interface x = {ptr, d, getConcreteStuff };
return x;
}
Interface Dependency2_new(Interface* ptr){
Dependency2* d = malloc(sizeof(*d));
d->concreteStuff2 = 2;
struct Interface y = {ptr, d, getConcreteStuff };
return y;
}
//context
typedef struct {
Interface i;
} Context;
void Context_doSomething(Context* ctx, Type t){
printf("%d\n", ctx->i.getConcreteStuff(&ctx->i, t));
}
int main(){
Context ctx1 = { Dependency1_new(NULL) };
Context_doSomething(&ctx1, DEP1);
Context ctx2 = { Dependency2_new(&ctx1.i) };
Context_doSomething(&ctx2, DEP2);
Context ctx3 = { *ctx2.i.ptr };
Context_doSomething(&ctx3, DEP1);
return 1;
}

Related

C: Reading property of struct pointer causes property to change?

I have a program that stores two different structs (tri & quad) in an array of a special struct defined below:
struct inst_ptr
{
void* p;
unsigned type;
};
The structs tri & quad have a superbase property
The following code displays how the structs are defined:
struct inst
{
char name[50];
int id;
};
struct tri
{
struct inst superbase;
};
struct quad
{
struct inst superbase;
};
Function for creating new instances (all located outside of main):
struct inst_ptr insts[100]; //instance container
int cinsts=0; //instance count
int inst_new(int type)
{
switch(type)
{
case TYPE_TRI:
{
struct tri i;
insts[cinsts].p=&i;
}
case TYPE_QUAD:
{
struct quad i;
insts[cinsts].p=&i;
}
}
insts[cinsts].type=type;
cinsts++;
return cinsts-1; //return index of instance in array
}
In my main function I create a sample tri, writing and reading it's values:
struct tri* t1=(struct tri*)insts[inst_new(TYPE_TRI)].p;
strcpy(t1->superbase.name, "tri1");
t1->superbase.id=70;
printf("id: %d\n", t1->superbase.id);
printf("id: %d\n", t1->superbase.id); <- problem occurs here and onward
Printing the id the first time works, printing 70 in the output. However, the second time it prints a long random integer.
Output:
id: 69
id: 1973802146
id: 1973802146
As you shown above, after the second read it keeps printing 1973802146. I'm not really sure what I'm doing wrong but I have a feeling I'm missing an extremely basic concept relating to pointers and structs.
You are saving the address of local variables in the array. That's bad because those variables doesn't exist once the function returns. You should use dynamic allocation instead.
Besides that you switch need break statements. And perhaps also a default case.
Like:
int inst_new(int type)
{
switch(type)
{
case TYPE_TRI:
{
struct tri *p = malloc(sizeof *p);
if (p == NULL) exit(1);
insts[cinsts].p=p;
break;
}
case TYPE_QUAD:
{
struct quad *p = malloc(sizeof *p);
if (p == NULL) exit(1);
insts[cinsts].p=p;
break;
}
default:
{
// Unknown type.. add error handling here
exit(1);
}
}
insts[cinsts].type=type;
cinsts++;
return cinsts-1; //return index of instance in array
}
As an alternative you can do:
int inst_new(int type)
{
insts[cinsts].p = NULL
switch(type)
{
case TYPE_TRI:
{
insts[cinsts].p=malloc(sizeof(struct tri));
break;
}
case TYPE_QUAD:
{
insts[cinsts].p=malloc(sizeof(struct quad));
break;
}
}
if (insts[cinsts].p == NULL) exit(1); // malloc failed
insts[cinsts].type=type;
cinsts++;
return cinsts-1; //return index of instance in array
}

How to create prototype that references a double located with in a struct located within a linked list?

I'm currently creating a program to interpolate linear regressions on missing entries in a time series. IE Col 2 Row 20-30 is missing the program would take col 2 row 19 (for instance 10) and col 2 row 30 (20) then fill in the NULL values linearly ie 11, 12, 13. I have multiple columns which have NULL values, so to do this I want to create a struct
struct missingPoint
{
double lastVal;
struct node * ptrtoLast;
int missingVals;
};
struct point
{
double col1;
double col2;
double col3;
};
typdef struct point Tick;
typedef struct node
{
Tick tick;
struct node * next;
} Node;
typedef Node * List;
So the idea is to write a prototype then a function which takes *ptrtoList->tick.colx as an argument as well as the missingPoint struct then I can iterate it the col and fill in the missing time series data, it iterates the column storing ptrs to nodes which contain non-NULL entries for the Col, when it hits a NULL val, it has the ptr to the last node with non-null val, it iterates until it gets a non-Null value again then using the ptr it has stored in memory it iterates back through and replaces the Null values with a linear regression between the two poitns. But I don't know how I can specify a double which occurs inside a struct which is pointed to by another struct for a function and function prototype, with that function I could just call the function for every column I have, without it I'd have to hardcode quite a bit which I'd like to avoid. Any advice would be greatly appreciated.
So the function would be like this, this currently has the column hard coded, I'd like to pass the column number as an argument so that I can multithread it, and call the function multiple times since the matrices I'm looking at are quite big, and because I'd like to practice concurrent programming:
void crawlOne(List *plist)
{
Node * last;
double lastVal, tmp;
int i, count = 0;
Node * pnode = *plist;
while(pnode != NULL)
{
last = pnode->next;
pnode = pnode->next;
if(pnode->tick.col1=NULL)
{
while(pnode->tick.col1=NULL)
{
count ++;
pnode = pnode->next;
}
tmp = lastVal-pnode->tick.col1;
pnode = last;
for(i=0;i<count;i++)
{
pnode = pnode->next;
pnode->tick.col1 = lastVal + i*(tmp/count);
i++;
}
}
}
}
Generally: Just define the function multiple times. No, C doesn't have templates.
The best: Generalize your data by providing an interface to manipulate it via function pointers - such interface is typically a virtual table. In your case a single function pointer to access the underlying data by a read/write handle looks enough. This effectively pulls the variant/changing/non-constant parts of the function into a different place. Allow users to pass an additional generic argument so that users can pass custom context:
void crawlOne(List *plist, double *(*getcol)(void *arg, struct point *p), void *arg)
{
// tmp = lastVal-pnode->tick.col1;
double tmp = *getcol(arg, &lastVal-pnode->tick);
...
// pnode->tick.col1 = lastVal + i*(tmp/count);
*getcol(arg, &pnode->tick) = lastVal + i*(tmp/count);
...
}
double *point_getCol1(void *arg, struct point *p) {
return &p->col1;
}
double *point_getCol2(void *arg, struct point *p) {
return &p->col2;
}
double *point_getCol3(void *arg, struct point *p) {
return &p->col3;
}
int main() {
crawlOne(plist, point_getCol2, NULL);
crawlOne(plist, point_getCol3, NULL);
}
In your case you can pass offsetof to members in point and dereference a pointer to double* at proper positions. This is not flexible and invites bugs, because it doesn't statically check types:
void crawlOne(List *plist, size_t coloffset)
{
...
// tmp = lastVal-pnode->tick.col1;
double tmp = *(double*)((char*)&lastVal-pnode->tick + coloffset);
...
// pnode->tick.col1 = lastVal + i*(tmp/count);
*(double*)((char*)&pnode->tick + coloffset) = lastVal + i*(tmp/count);
...
}
int main() {
crawlOne(plist, offsetof(struct point, col1));
crawlOne(plist, offsetof(struct point, col2));
}
It's common to use a macro to ease up defining the function multiple times (only do if you really know what you are doing). Such tends to become hard to maintain, and is hard to debug:
#define DECLARE_CRAWL_ONE(FUNC, MEMBER) \
void FUNC(List *plist) \
{ \
/* tmp = lastVal-pnode->tick.col1; */ \
double tmp = lastVal-pnode->tick.MEMBER; \
... \
/* pnode->tick.col1 = lastVal + i*(tmp/count); */ \
lastVal-pnode->tick.MEMBER = lastVal + i*(tmp/count); \
... \
}
DECLARE_CRAWL_ONE(crawlOnecol1, col1)
DECLARE_CRAWL_ONE(crawlOnecol2, col2)
DECLARE_CRAWL_ONE(crawlOnecol2, col2)
So to summarize:
You have a function crawlOne(List *plist) that locates some objects of type struct point and does something to their col1 members.
You would like to have a function crawlSome(List *plist, int colnum) which:
when called as crawlSome(list, 1) operates on col1
when called as crawlSome(list, 2) operates on col2
and so on.
By far the cleanest approach, as John Bollinger suggested in a comment, is to redesign struct point to contain an array instead of three separate members:
struct point {
double col[3];
};
void crawlSome(List *plist, int colnum) {
// ...
pnode->tick.col[colnum] = ...;
}
This does mean that you have to change all existing code that uses struct point, which although straightforward could be tedious, but in the long term you have a cleaner and more efficient design. I would do this if at all possible.
If you really cannot change the definition of struct point (e.g. it is used by third-party code that you can't modify), then you can't avoid hardcoding the member names somehow, since the names don't exist at runtime. KamilCuk has suggested some options for this. Another that I might think of is to pull out the hardcoding into a "column selector" function, so that it only has to be done at one place in your program. It should not be too inefficient if it can be inlined.
inline double *select_column(struct point *pt, int colnum) {
switch (colnum) {
case 1: return &pt->col1;
case 2: return &pt->col2;
case 3: return &pt->col3;
default: abort(); // or perhaps return NULL;
}
}
void crawlSome(List *plist, int colnum) {
// ...
*select_column(&pnode->tick, colnum) = ...
}
This avoids the need to duplicate the code of crawlOne at all, with or without a macro.
If you want to reduce the repetition in defining select_column, you can use a macro with token pasting:
inline double *select_column(struct point *pt, int colnum) {
switch (colnum) {
#define DO(N) case N: return &pt->col ## N ;
DO(1)
DO(2)
DO(3)
#undef DO
default: abort(); // or perhaps return NULL;
}
}
If you want to make the selector a little nicer to use, you can wrap it in a macro:
#define COL(p, n) (*select_column(&(p), (n)))
void crawlSome(List *plist, int colnum) {
// ...
COL(pnode->tick, colnum) = ...;
}
Alternatively, a similar approach can be implemented with offsetof, though with the same lack of type checking that KamilCuk points out:
#include <stddef.h>
const size_t col_offsets[3] = {
offsetof(struct point, col1),
offsetof(struct point, col2),
offsetof(struct point, col3)
};
#define COL(p, n) (*(double *)((char *)&(p) + col_offsets[(n)]))

Variabe type for variable inside function

I'm having different different types of structs, which are going to be passed to a function which performs the same tasks on them.
int menu_parameter_arrow_print(game_setting_identifier* identifier, controller_direction direction, uint8_t position)
{
if((position > setting->alternatives_number) || position < 0)
{
#ifdef OLED_PRINT_DEBUG_ENABLE
OLED_debug_print("Out of bounds");
#endif
return RETURN_VALUE_FAILURE;
}
else
{
switch ((int)*identifier)
{
case ((int) GAME_SETTING_ANALOG):
game_setting_analog* setting = (game_setting_analog*)&identifier;
case ((int) GAME_SETTING_TOGGLE):
game_setting_toggle* setting = (game_setting_toggle*)&identifier;
case ((int) GAME_SETTING_VALUE):
game_setting_value* setting = (game_setting_value*)&identifier;
}
This function gives a conflicting type-error
The operations performed on the structs are the same, but the structs contains different types of members:
struct game_setting_analog
{
//Identifier for the game-setting type:
game_setting_identifier identifier;
//Alternatives:
char* alternatives[4];
};
typedef struct game_setting_value game_setting_value;
struct game_setting_value
{
game_setting_identifier identifier;
uint8_t* alternatives[6];
uint8_t alternatives_number;
};
typedef struct game_setting_toggle game_setting_toggle;
struct game_setting_toggle
{
//Identifier for the game-setting type:
game_setting_identifier identifier;
toggle_state* alternatives[2];
};
typedef struct game_setting_difficulty game_setting_difficulty;
struct game_setting_difficulty
{
game_setting_identifier identifier;
char* alternatives[3];
};
Actions will be performed on the 'alternatives'-member of the structs, even though these members are of different types.
Is there a solution to doing this without having to use one if-statement for each identifier?
Edit: With a modification to the switch-case, I'm able to get the initialization compiled. The variables inside the switch-scope is however not visible to the rest of the function
int menu_print_parameter_line(game_setting_identifier* identifier, controller* C, uint8_t position)
{
uint8_t next_position = position;
controller_direction previous_direction = C->joystick.generalDirection;
if ((identifier == NULL) || (C == NULL) || (position == NULL))
{
return -1;
}
switch((int) identifier)
{
case ((int) GAME_SETTING_ANALOG):
{
game_setting_analog* setting = (game_setting_analog*)identifier;
uint8_t alternatives_number = 4;
}
break;
case ((int) GAME_SETTING_TOGGLE):
{
game_setting_toggle* setting = (game_setting_toggle*)identifier;
uint8_t alternatives_number = 2;
}
break;
case ((int) GAME_SETTING_VALUE):
{
game_setting_value* setting = (game_setting_value*)identifier;
uint8_t alternatives_number = setting->alternatives_number;
}
break;
default:
{
return -1;
}
break;
}
#ifdef MENU_PARAMETER_ASSIGNMENT_DEBUG
OLED_debug_print("before switch-case");
#endif
switch (previous_direction)
{
case LEFT:
next_position -= 1;
if(next_position <= 0)
{
next_position = alternatives_number;
}
I personally don't like the inheritance model that depends on the first member of the structure, like the BSD socket library is using. Basically you are just trying to implement std::variant from c++ in C.
Is there a solution to doing this without having to use one if-statement for each identifier?
The object-oriented concept of interface works very nice and I believe is applicable in this case. It takes some C discipline to write it, but it works like a charm and you could be looking for it here.
I copied your definitions from which I removed typedefs because I don't like them:
struct game_setting_analog {
char* alternatives[4];
};
struct game_setting_value {
uint8_t* alternatives[6];
uint8_t alternatives_number;
};
struct game_setting_toggle {
toggle_state* alternatives[2];
};
struct game_setting_difficulty {
char* alternatives[3];
};
Let's first implement the interface abstraction with a function pointer that allows to get the alternatives number:
// forward definition
struct game_setting_s;
// the virtual table for game_settings
struct game_setting_vtable_s {
uint8_t (*get_alternatives_number)(struct game_setting_s *t);
// TODO: add other members, constructor, copy constructor, destructor, etc.
};
// represents any game_setting
// exposes a public interface to access and manipulate a game_setting
struct game_setting_s {
// the vtable is const, so it can save RAM
const struct game_setting_vtable_s *v;
// this is a pointer to private settings data
void *data;
};
// accessor for less (or more ;) typing
static inline
uint8_t game_setting_get_alternatives_number(struct game_setting_s *t) {
// alternative you could pass t->data to the function, I pass it all
// so that functions can modify the t->data member
// and also so that advanced functions usages can use like container_of macros
return t->v.get_alternatives_number(t);
}
Then you need to provide the virtual tables for each of the types. The definitions can be in separate types, so you can have a separate .c/.h file pair for each of the type, just exposing public interface.
// game_setting_analog --------------------
static
uint8_t game_setting_analog_get_altenatives_number(struct game_setting_s *t)
{
return 4;
}
const struct game_setting_vtable_s game_setting_analog_vtable = {
.get_alternatives_number = game_setting_analog_get_altenatives_number,
};
// game_setting_toggle --------------------
static
uint8_t game_setting_toggle_get_altenatives_number(struct game_setting_s *t) {
struct game_setting_toggle *data = t->data;
return data->alternatives_number;
}
const struct game_toggle_vtable_s game_setting_toggle_vtable = {
.get_alternatives_number = game_setting_toggle_get_altenatives_number,
};
// and so on...
Then your function takes just the interface and is very clear without any switch case:
int some_function_that_needs_to_know_which_setting_is_passed(struct game_setting_s *s) {
int number_of_alternatives = game_setting_get_alternatives_number(s);
}
Remember to construct the interface object properly and watch who owns the memory of the object. Let's construct a toggle and call out function:
struct game_settting_toggle memory;
// your function to initialize the toggle
game_setting_toggle_intialize(&memory);
// the interface is constructed with the proper vtable
// and a pointer to proper memory region with the data
struct game_setting_s any_setting = {
.vtable = game_setting_toggle_vtable,
.data = &memory,
};
// the initailize function could be in interface too
// so you would just call game_setting_initialize(&any_setting);
// with usage of dynamic allocation, you can just ex.
// struct game_setting_s *any_setting = game_setting_new_toggle();
// and write proper object-oriented factories
// finally call our function.
some_function_that_needs_to_know_which_setting_is_passed(&any_setting);
Case labels do not provide scopes for variables. All three setting variables within the switch have different types which are the conflicts the compiler. Use brackets to define scopes:
switch ((int)*identifier)
{
case ((int) GAME_SETTING_ANALOG):
{
game_setting_analog* setting = (game_setting_analog*)&identifier;
}
case ((int) GAME_SETTING_TOGGLE):
{
game_setting_toggle* setting = (game_setting_toggle*)&identifier;
}
case ((int) GAME_SETTING_VALUE):
{
game_setting_value* setting = (game_setting_value*)&identifier;
}
}
Also, you're not breaking in the cases, so the code in all three cases are run if ((int)*identifier == (int) GAME_SETTING_ANALOG)

Memory allocation error for structs with members that are function pointers and void pointers

I have written a straightforward C code that uses an engine to run two different algorithms depending on user input. It uses function pointers to the algorithm methods and objects. There is a nasty memory bug somewhere that I can not track down, so maybe I am allocating memory in the wrong way. What is going wrong?
Below is (the relevant parts of) a minimal working example of the code.
main.c
#include "engine.h"
int main()
{
char *id = "one";
Engine_t eng;
Engine_init(&eng);
Engine_select_algorithm(eng, id);
Engine_run(eng);
}
engine.h
typedef struct _Engine *Engine_t;
engine.c
#include "engine.h"
#include "algorithm_one.h"
#include "algorithm_two.h"
typedef struct _Engine
{
void *p_algorithm;
void (*init)(Engine_t);
void (*run)(Engine_t);
} Engine;
void Engine_init(Engine_t *eng)
{
*eng = malloc(sizeof(Engine));
(*eng)->p_algorithm = NULL;
}
void Engine_select_algorithm(Engine_t eng, char *id)
{
if ( strcmp(id, "one") == 0 )
{
eng->init = Algorithm_one_init;
eng->run = Algorithm_one_run;
}
else if ( strcmp(id, "two") == 0 )
{
eng->init = Algorithm_two_init;
eng->run = Algorithm_two_run;
}
else
{
printf("Unknown engine %s.\n", id); exit(0);
}
eng->init(eng);
}
void Engine_run(Engine_t eng)
{
eng->run(eng);
}
void Engine_set_algorithm(Engine_t eng, void *p)
{
eng->p_algorithm = p;
}
void Engine_get_algorithm(Engine_t eng, void *p)
{
p = eng->p_algorithm;
}
algorithm_one.h
typedef struct _A_one *A_one_t;
algorithm_one.c
#include "engine.h"
#include "algorithm_one.h"
typedef struct _A_one
{
float value;
} A_one;
void Algorithm_one_init(Engine_t eng)
{
A_one_t aone;
aone = malloc(sizeof(A_one));
aone->value = 13.0;
//int var = 10;
Engine_set_algorithm(eng, &aone);
}
void Algorithm_one_run(Engine_t eng)
{
A_one_t aone;
Engine_get_algorithm(eng, &aone);
printf("I am running algorithm one with value %f.\n", aone->value);
// The code for algorithm one goes here.
}
The code for algorithm_two.h and algorithm_two.c are identical to the algorithm one files.
There must be a memory bug involved, because the code runs as given, but if I uncomment the
//int var = 10;
line in algoritm_one.c the code crashes with a segmentation fault.
You pass the wrong thing to Engine_set_algorithm. You are passing the address of a local variable rather than the address of the algorithm. You need to write:
Engine_set_algorithm(eng, aone);
And also Engine_get_algorithm is wrong. You are passed a pointer by value and modify that pointer. So the caller cannot see that modification. You need it to be:
void Engine_get_algorithm(Engine_t eng, void **p)
{
*p = eng->p_algorithm;
}
I think your code would be easier if you defined a type to represent an algorithm. That type would be just a void*, but it would make the code much easier to read. What's more, I would make Engine_get_algorithm return the algorithm.
algorithm Engine_get_algorithm(Engine_t eng)
{
return eng->p_algorithm;
}
void Engine_set_algorithm(Engine_t eng, algorithm alg)
{
eng->p_algorithm = alg;
}

How to make struct members private?

I define a structure in a header file like so:
typedef struct {
void *data;
} point;
I want to keep other people from accessing *data directly, so I thought I'd declare the structure in the .c file instead and use something like extern typedef struct point; in the header file. That doesn't work however.
What's the best way to achieve this?
In your (public) header file:
typedef struct point point;
In your .c file:
struct point
{
void *data;
};
Note that users of your code will no longer be able to create a point on the stack, as the compiler doesn't know how big it is. You may have to provide a point_create() function which allocates memory and returns its address to the caller.
Use C++
Since jokes seem not be allowed here is the pure C version.
As another commenter pointed out if you really want to protect your internals from users of your Api you have seen and used plenty of such Apis. This Apis are e.g. the Windows or Linux user mode Apis. There you create kernel objects to which you never shall have access to. The Apis to deal with kernel objects use a synthetic construct called handle which is not simply a pointer to your own object but instead it is an index to an array where the kernel has stored the relevant meta data for your object.
You can use the same idea for your Apis as well.
Here for example is a C-Style public Api:
// Public.h
#include <stdlib.h>
typedef enum
{
None = 0,
PointType = 1
} Types;
typedef int Handle;
Handle CreateType(Types type);
int DeleteType(Handle object);
void IncrementX(Handle point);
void PrintPoint(Handle point);
As you can see you have generic methods which create and delete your objects which are defined here in an enum. Your methods which use the object will then need to lookup the integer handle to get the meta data object where the real data is stored.
This design is not very efficient if the objects you manage are small since for every object a second object is need which stores the object type, handle value and the pointer to the real data.
But you get much stronger safety guarantees such as
Type safety
Invalid handles are easy to find
Double free is impossible since you can manage the free state in the meta object
A typical usage of your Api might look like this:
Handle h = CreateType(PointType);
IncrementX(h);
IncrementX(h);
PrintPoint(h);
DeleteType(h);
And there is the super secret implementation in private.cpp where the Handle lookup array and some helper methods exist:
// Private.C
#include "stdafx.h"
#include <stdlib.h>
#include <Windows.h> // for ZeroMemory
#include "Public.h"
typedef struct
{
LPVOID pData;
Types type;
Handle handle;
} HandleInfo;
typedef struct
{
int x;
int y;
} Point;
HandleInfo *pAllocated;
int HandleBuffer = 0xffff;
unsigned char bInit = 0;
HandleInfo *GetFreeHandle()
{
int i;
if( !bInit )
{
pAllocated = (HandleInfo *) malloc(sizeof(HandleInfo)*HandleBuffer);
bInit = 1;
ZeroMemory(pAllocated, sizeof(HandleInfo)*HandleBuffer);
}
for(i=0; i<HandleBuffer; i++)
{
HandleInfo *pInfo = (pAllocated+i);
if( 0 == pInfo->handle )
{
pInfo->handle = i+1;
return pInfo;
}
}
return NULL;
}
HandleInfo * GetHandleInfo(Handle h)
{
if( h <= 0 || h >= HandleBuffer-1)
{
return NULL;
}
return (pAllocated+h-1);
}
Handle CreateType(Types typeId)
{
HandleInfo *pInfo;
pInfo = GetFreeHandle();
if( NULL == pInfo )
{
return -1;
}
pInfo->type = typeId;
switch(typeId)
{
case PointType:
pInfo->pData = malloc(sizeof(Point));
ZeroMemory(pInfo->pData, sizeof(Point));
break;
}
return pInfo->handle;
}
int DeleteType(Handle object)
{
HandleInfo *pInfo = GetHandleInfo(object);
if( NULL == pInfo )
{
return -1;
}
if( pInfo->handle != 0 )
{
free(pInfo->pData);
pInfo->pData = NULL;
pInfo->handle = 0;
return 1;
}
else
{
return 0; // Handle was already closed
}
}
void *GetObjectOfCorrectType(Handle object, Types type)
{
HandleInfo *p = GetHandleInfo(object);
if( p == NULL )
{
return NULL;
}
if( p->type != type)
{
return NULL; // handle has wrong object type
}
return p->pData;
}
void IncrementX(Handle point)
{
Point *pPoint = (Point *) GetObjectOfCorrectType(point, PointType);
if( pPoint == NULL )
{
return;
}
pPoint->x++;
}
void PrintPoint(Handle point)
{
Point *pPoint = (Point *) GetObjectOfCorrectType(point, PointType);
if( pPoint == NULL )
{
return;
}
printf("Point has x: %d y: %d", pPoint->x, pPoint->y);
}
Yours,
Alois Kraus
This is the pointer to implementation or pimpl idiom. See http://en.wikibooks.org/wiki/C++_Programming/Idioms#Pointer_To_Implementation_.28pImpl.29 for a tutorial for C++, but the idea should work in C as well.
typedef struct {
/* private members; don't access directly */
void *data;
} point;
You can have separate public header and private header files. Some libraries have conventions for this:
Xt (X11) -> header.h and headerP.h, e.g: X11/Vendor.h vs X11/VendorP.h
Qt -> header.h vs private/header_p.h, e.g: qapplication.h vs private/qapplication_p.h
If you do not want to use the declaration method (because you want the library user to access other members of your struct, for example) it is convention to prepend private member with an underscore, like this:
typedef struct {
void * _data;
} point;
Of course people could still access _data if they would really want to (just like people can access private data in C++ by adding a #define private public before their includes) but that is their own responsibility; at least you have indicated that they shouldn't do that if they want your library to behave as it should.
I use this approach in order to let client alloc the module instance in his STACK.
struct module_private {
int data;
}
typedef uint8_t module_t [sizeof (struct module_private) ];
Client will be able to see private struct content, but not access it without doing a cast that he shouldn't.
Use the following workaround:
#include <stdio.h>
#define C_PRIVATE(T) struct T##private {
#define C_PRIVATE_END } private;
#define C_PRIV(x) ((x).private)
#define C_PRIV_REF(x) (&(x)->private)
struct T {
int a;
C_PRIVATE(T)
int x;
C_PRIVATE_END
};
int main()
{
struct T t;
struct T *tref = &t;
t.a = 1;
C_PRIV(t).x = 2;
printf("t.a = %d\nt.x = %d\n", t.a, C_PRIV(t).x);
tref->a = 3;
C_PRIV_REF(tref)->x = 4;
printf("tref->a = %d\ntref->x = %d\n", tref->a, C_PRIV_REF(tref)->x);
return 0;
}
Result is:
t.a = 1
t.x = 2
tref->a = 3
tref->x = 4

Resources