Something like this:
Code:
// screen.h
#ifdef SCREEN_H_INCLUDED
#define SCREEN_H_INCLUDED
typedef struct screen_obj screenObj;
screenObj *myScreenInit( void );
void myScreenClear ( screenObj *s );
#endif
Code:
// screen_win32.c
#include "screen.h"
#include <windows.h>
struct screen_obj {
int a;
};
screenObj *myScreenInit( void ) {
screenObj *s = malloc( sizeof(*s) );
s->a = 42;
return s;
}
void myScreenClear( screenObj *s ) {
printf("%d\n", s->a );
}
Code:
// screen_linux.c
#include "screen.h"
#include <ncurses,h>
struct screen_obj {
char *p;
};
screenObj *myScreenInit( void ) {
screenObj *s = malloc( sizeof(*s) );
s->p = "hello";
return s;
}
void myScreenClear( screenObj *s ) {
printf("%s\n", s->a );
}
Code:
// main.c
#include "screen.h"
int main ( ) {
screenObj *s = myScreenInit();
myScreenClear(s);
return 0;
}
Now the real magic is:
For a win32 project, you compile main.c and screen_win32.c
For a Linux project, you compile main.c and screen_linux.c
Porting to another platform, you just write a new screen_xxx.c file.
main.c at that point couldn't give a hoot.
Notice in the header file, the screen is declared as an incomplete type. This means that all main can ever do is maintain a pointer and never dereference it.
Also note that inside each implementation file, the struct is declared to be whatever we need it to be. Maybe you don't need an object for the win32 case. But it generally makes for easier porting later on if you do need one.
It also easily paves the way for multi-screen use