FPL - a single header file platform abstraction library

Started by
36 comments, last by Finalspace 6 years ago

Hi,

i wanted to present you my recent project i am working on which is a platform abstraction library.
This library is designed to be simple, non-bloated, can be included however you want and do not require any thirdparty libraries at all. It will simply abstract away all relevant platform specific things in a simple to use api without hiding any data. The main focus is game/media/simulation development, so you get a window, audio playback and a rendering context.

 

Why:

- Moving away from object orienation to handmade programming
- Most platform abstraction libraries are bloated, have a bad api, cannot be debugged, are slow, has bad memory management
- I dont want to write platform specific code anymore, just once for each platform with a fixed set of features and thats it.
- Learning C99 low level programming

 

Mindset:

- Its written in C99 but is C++ compatible
- There is just a single header file you have to include and thats it.
- C-Runtime support can be disabled
- The code style is simple and clean
- Its full open source, so you can use and extend it however you want
- Uses just the built-in operating system functions/libraries
- Works well with other libraries as well (ImGUI, Box2D, Glew, STL, etc.)
- Some features can be compiled out as needed (Window, OpenGL, etc.)
- Fixed and small memory footprint
- Easy to use api
- Can be debugged

 

Features:

- Window creation and handling
- OpenGL legacy and modern rendering context creation
- Memory allocation and deallocation
- Timing operations
- Threading and syncronisation
- File/Path IO
- String conversion functions
- Atomic operations
- Dynamic library loading
- Console out
- Gamepad input
- Audio playback

 

History:

Initially the project was fully written with 100% C/89 compability in mind without needing the c-runtime library, but as i see myself always fighting against C or missing any features like console output, i decided to move to a minimal C++ version.

After a while i upgraded to C++/11, but felt there was no need for C++ at all...

Now its written in C99 and it was the best choice ever.

 

Current state:

- Win32 support is complete
- Linux support is almost complete

 

Planned:

- More video drivers (Direct2D/3D/Vulcan)
- More audio drivers (XAudio, Wasapi)
- More platforms (MacOSX, maybe Android not sure)
- More docs & tutorials
- More tests

 

Source:

https://github.com/f1nalspace/final_game_tech

 

Feedback/Comments:

I would like to know what you think about, what is missing, how can i improve it, what do you want from it, etc.

 

Greetings,
Final

Advertisement

I skimmed your code and there are two (maybe three) things that stuck out to me.


#define FPL_NULL 0

This is not how you should be defining NULL. Either use (void*)0 or nullptr if C++11 is available.


#if !FPL_ENABLE_C_RUNTIME_LIBRARY
void __stdcall WinMainCRTStartup() {
    int result = wWinMain(GetModuleHandleW(0), 0, 0, 0);
    ExitProcess(result);
}
#endif // !FPL_ENABLE_C_RUNTIME_LIBRARY

I read your comment further up the file about how you hate the CRT, but this is clearly taking it too far. I'll quote a section of ExitProcess()'s documentation:

Quote

Calling ExitProcess in a DLL can lead to unexpected application or system errors. Be sure to call ExitProcess from a DLL only if you know which applications or system components will load the DLL and that it is safe to call ExitProcess in this context.

And that's pretty much the point at which I stopped reading your code. Parts of it looked good, other parts looked really, really bad. A more important question to me is: Who needs this? Why does this exist? All of this stuff is already available in other libraries or game frameworks.

As a side note, why are people writing more and more of these "header only" libraries? The preprocessor seems like a flimsy way to configure how your code should compile. A more solid solution is to use a proper build system.

"I would try to find halo source code by bungie best fps engine ever created, u see why call of duty loses speed due to its detail." -- GettingNifty
51 minutes ago, TheComet said:

I skimmed your code and there are two (maybe three) things that stuck out to me.



#define FPL_NULL 0

This is not how you should be defining NULL. Either use (void*)0 or nullptr if C++11 is available.



#if !FPL_ENABLE_C_RUNTIME_LIBRARY
void __stdcall WinMainCRTStartup() {
    int result = wWinMain(GetModuleHandleW(0), 0, 0, 0);
    ExitProcess(result);
}
#endif // !FPL_ENABLE_C_RUNTIME_LIBRARY

I read your comment further up the file about how you hate the CRT, but this is clearly taking it too far. I'll quote a section of ExitProcess()'s documentation:

And that's pretty much the point at which I stopped reading your code. Parts of it looked good, other parts looked really, really bad. A more important question to me is: Who needs this? Why does this exist? All of this stuff is already available in other libraries or game frameworks.

As a side note, why are people writing more and more of these "header only" libraries? The preprocessor seems like a flimsy way to configure how your code should compile. A more solid solution is to use a proper build system.

I tried FPL_NULL (void *)0 - but i had trouble with it, so i simply set it to zero. But yes i agree, using nullptr on C++/11 would be better, but how do i detect if C++/11 is available - through preprocessor directives? Btw. FPL_NULL is internal only, so its not meant to be used outside.

 

That entire no CRT thing - i am not sure about this. Its a experiment to see if it works, because some people dont want to include even the C-Runtime Library at all. Also regards DLL´s and ExitProcess and need to think it more, as a matter of fact i havent created a library project yet - but this will come soon. When i see that no-CRT is support is too complicated, i will drop it. Right know i dont see any benefit disabling CRT, except for smalling out the executable size.

 

Why header library only? Because its simple and works all the time. No linking madness, no dll´s needed - besides from the standard system operating stuff which is included anyway.

 

Regards build-systems: I dont like build-systems at all, all i ever used was just awful: Slow, hard to configure, not working -> On any programming language the same bad experience.

But what i will do for sure, is making several simple build scripts (Batch, Shell) which just builds the samples in the simplest possible way for a set of compilers/platforms.

52 minutes ago, Finalspace said:

C++/11 would be better, but how do i detect if C++/11 is available - through preprocessor directives?

You have it in your own code:


	#ifdef __cplusplus
	

Quote

That entire no CRT thing - i am not sure about this. Its a experiment to see if it works, because some people dont want to include even the C-Runtime Library at all. 

I do not know a person or a product that does not link with CRT. Starting form small games, 3D DCCs, even some "serious software" uses it.
 

Quote

Why header library only? Because its simple and works all the time. No linking madness, no dll´s needed - besides from the standard system operating stuff which is included anyway.

A header and a *.cpp is equally simple to me.
 


#define fpl_globalvar static
#define fpl_inline inline
#define fpl_internal static
#if FPL_API_AS_PRIVATE
#    define fpl_api static
#else
#    define fpl_api extern

This is unnecessary code to me, it doesn't tell much to the reader and these have no functional benefit, actually it is wrong:
if I "fpl_globalvar int x;" in a *.cpp this will actually make the variable "private" to that *.cpp, making it inaccessible to other files.

40 minutes ago, ongamex92 said:

I do not know a person or a product that does not link with CRT. Starting form small games, 3D DCCs, even some "serious software" uses it.
 

A header and a *.cpp is equally simple to me.
 



#define fpl_globalvar static
#define fpl_inline inline
#define fpl_internal static
#if FPL_API_AS_PRIVATE
#    define fpl_api static
#else
#    define fpl_api extern

This is unnecessary code to me, it doesn't tell much to the reader and these have no functional benefit, actually it is wrong:
if I "fpl_globalvar int x;" in a *.cpp this will actually make the variable "private" to that *.cpp, making it inaccessible to other files.

Insomniac Games and EA for example do not use the C standard library, they even dont use the STL.

Also there are others people in the industry who do not use the C standard library as well.

For myself, i dont care but its great when you have the option to not need to ship the C Runtime with your game (VC++ redist for example).

 

Static has more than one meaning, private scope for this file only, local persisting state, global variable, class field in c++, etc. Even though it just mean: Private in this file only. Techniqually there are no differences between all of them, but this way you see right away which scope its meant to be in.

 

Right, there are no difference between header and source files. C++ has no definition of a file, you just have translation units which gets compiled to object files - thats it. I dont want to force users to have a separate translation unit, just for the library - if they want, they can have one but its not required.

 

1 hour ago, Finalspace said:

how do i detect if C++/11 is available - through preprocessor directives?

https://stackoverflow.com/a/29407260/4383258


#if defined(__cplusplus) && __cplusplus >= 201103L
#define FPL_NULL nullptr
#endif

 

"I would try to find halo source code by bungie best fps engine ever created, u see why call of duty loses speed due to its detail." -- GettingNifty
1 minute ago, TheComet said:

 

https://stackoverflow.com/a/29407260/4383258



#if defined(__cplusplus) && __cplusplus >= 201103L
#define FPL_NULL nullptr
#endif

 

Thanks, i already did that. Will commit that later ;)

- I added C++/11 nullptr support and renamed FPL_NULL to FPL_NULLPTR. Fallback is (void *)0

This topic is closed to new replies.

Advertisement