Sign in to follow this  
Finalspace

FPL - a single header file platform abstraction library

Recommended Posts

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.
The main focus is game or simulation development, so you get a window and a rendering context plus Memory/IO/Threading and more.

 

Why a single header platform abstract library these days?

- There is not a single one out there, which do not require a ton of DLL´s or Libs just for the library itself.
- I dont want C-Runtime linking madness anymore
- Most are bloated and are far beyond abstracting the platform
- Bad or no control how memory is being handled
- There is no good single header platform abstraction library out there
- I dont want to write platform specific code anymore, just once for each platform with a fixed set of features and thats it.

- Debugging when you have issues with platform specific things is near impossible

 

Mindset:

- Its written in C++/98, so its much easier to get it compile and running on other platforms as well
- There is just a single header file you have to include and thats it
- Its full open source, so you can use and extend it however you want
- No data hiding in the code, you have control over everything
- Easy to use api
- Does not directly allocate any memory at all
- Uses just the built-in operating system functions/libraries and the C-Runtime library
- Works well with non platform-specific libraries as well (ImGUI, Box2D, etc.)
- Features can be compiled out as needed (Window, OpenGL, etc.)

- I want to debug everything if i want to without any hassle

- [Learning about low level operating system programming besides win32]

 

Features:

- Create/Handling a optional window
- Create a optional opengl rendering context on the window
- Memory allocation and deallocation
- Timing operations
- Threading
- File/Path IO
- Atomic operations
- Dynamic library loading (.dll / .so)
- Console out/in

- Gamepad input

 

Current state / Planned:

- Its not complete at all, buts its usable and works - so feedback is very appreciated
- Some API calls are weird, require more thinking or need to be simpler (fpl_ListFilesBegin, fpl_ListFilesNext, etc.)
- Only x86/x64 win32 platform for now

- Support for Direct2D/3D/Vulcan (Only to get it up and running)
- Audio output (XAudio, ALSA)
- Good useful automated testing
- More Guides and Samples
- More Platforms (Linux/Unix, maybe Android not sure)
- More compiling out options (Some prefer the C++ standard template library or other libraries)
- Moving utility functions into its own library which have nothing todo with the platform (fpl_ExtractFileName, fpl_RemoveEmptyDirectory)
- Let the user allocate memory for storing platform input events as well

 

Issues:

- Will not work with any other platform abstraction libraries, because they all do magic stuff with entry points and such - so they gets in the way

 

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, etc. All constructive non hating comments are welcome!

 

Greetings,
Final

Edited by Finalspace

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
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.

Edited by Finalspace

Share this post


Link to post
Share on other sites
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
	

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Edited by Finalspace

Share this post


Link to post
Share on other sites

A change of mind:

i will drop C support and change it to a more C++ ish api, but it will not be full blown object oriented. Also C runtime support will be dropped as well.

Edited by Finalspace

Share this post


Link to post
Share on other sites

I will definitely have a look at it but as most other people might, I have those platform specific stuff already build into my game engine from the beginning. Platform detection for PC and propably Console, Threads, Locking, Atomics, Extensions (via LoadLibrary and similar) and even a Window class as same as some graphics API dependent startup code

Share this post


Link to post
Share on other sites

New version:

 

- Dropped C support

- Dropped No-C-Runtime support

- Removed all FPL prefixes from functions and types

- Moved to a more c++ ish api (Namespaces, const reference, enum class, constexpr, nullptr)

- Nested namespaces to categorize certain things (window, memory, strings, atomics, threading, etc.)

Edited by Finalspace

Share this post


Link to post
Share on other sites
On 6.10.2017 at 9:04 PM, ferreiradaselva said:

You need a reference doc

If you add something like this https://github.com/ferreiradaselva/cgdfw/blob/master/REFERENCE.md  it will make things much easier.

Thanks i will do that - good idea!

Is there a way to export all my api structs and functions into that automatically?

Never mind, i will write a command line tool which does that.

Edited by Finalspace

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Forum Statistics

    • Total Topics
      627701
    • Total Posts
      2978700
  • Similar Content

    • By 123iamking
      I just recently start using OpenAL soft (actually not really use, I'm still struggle with setting this up).
      Setup OpenAL soft - Passed
      First, I grab the source of OpenAL soft, I just run CMake for this and build, here the CMake result.
      Using DirectX SDK directory: C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)/ Could NOT find ALSA (missing: ALSA_LIBRARY ALSA_INCLUDE_DIR) Could NOT find OSS (missing: OSS_INCLUDE_DIR) Could NOT find AudioIO (missing: AUDIOIO_INCLUDE_DIR) Could NOT find SoundIO (missing: SOUNDIO_LIBRARY SOUNDIO_INCLUDE_DIR) Could NOT find QSA (missing: QSA_LIBRARY QSA_INCLUDE_DIR) Could NOT find PortAudio (missing: PORTAUDIO_LIBRARY PORTAUDIO_INCLUDE_DIR) Could NOT find PulseAudio (missing: PULSEAUDIO_LIBRARY PULSEAUDIO_INCLUDE_DIR) Could NOT find JACK (missing: JACK_LIBRARY JACK_INCLUDE_DIR) CMake Warning at utils/alsoft-config/CMakeLists.txt:13 (find_package): By not providing "FindQt5Widgets.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "Qt5Widgets", but CMake did not find one. Could not find a package configuration file provided by "Qt5Widgets" with any of the following names: Qt5WidgetsConfig.cmake qt5widgets-config.cmake Add the installation prefix of "Qt5Widgets" to CMAKE_PREFIX_PATH or set "Qt5Widgets_DIR" to a directory containing one of the above files. If "Qt5Widgets" provides a separate development package or SDK, be sure it has been installed. Found unsuitable Qt version "" from NOTFOUND Could NOT find SDL2 (missing: SDL2_LIBRARY SDL2_INCLUDE_DIR) Building OpenAL with support for the following backends: WinMM, DirectSound, MMDevApi, WaveFile, Null Building with support for CPU extensions: Default, SSE, SSE2, SSE3, SSE4.1 Installing sample configuration Installing HRTF definitions Installing AmbDec presets Building utility programs Building test programs Building example programs Configuring done Generating done So I see that I have no Qt & SDL2 for my OpenAL-soft, hope that ok (I don't even know what it for, as long as the I can build OpenAL-soft, I don't really care)
      So setup OpenAL-soft seem easy.
      Setup alure - failed
      I got trouble when I setup alure,
      I setup CMake like this:
      OPENAL_INCLUDE_DIR = E:/Source/openal-soft/include/AL OPENAL_LIBRARY = E:/Source/_build/openal-soft/Release And I get the CMake result like this:
      Found OpenAL: E:/Source/_build/openal-soft/Release Could NOT find OGG (missing: OGG_LIBRARY OGG_INCLUDE_DIR) Could NOT find SndFile (missing: SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR) Could NOT find MPG123 (missing: MPG123_LIBRARY MPG123_INCLUDE_DIR) Could NOT find PhysFS (missing: PHYSFS_LIBRARY PHYSFS_INCLUDE_DIR) Could NOT find DUMB (missing: DUMB_LIBRARY DUMB_INCLUDE_DIR) Configuring done WARNING: Target "alure2" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2_s" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2_s" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2_s" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure2_s" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-play" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-play" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-play" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-play" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-enum" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-enum" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-enum" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-enum" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-hrtf" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-hrtf" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-hrtf" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-hrtf" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-reverb" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-reverb" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-reverb" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-reverb" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-stream" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-stream" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-stream" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. WARNING: Target "alure-stream" requests linking to directory "E:/Source/_build/openal-soft/Release". Targets may link only to libraries. CMake is dropping the item. Generating done So there are a lot of warnings. I lookup this warning and seem that this is just about the CMake programming inside the file CMakeLists.txt, for the meantime, I'll ignore it.
      Then I open the alure solution (alure.sln) with Visual Studio and build. Unfortunately, I got compile error
      Severity Code Description Project File Line Suppression State Error C3861 'strcasecmp': identifier not found alure-hrtf E:\Source\alure\examples\alure-hrtf.cpp 49 Error C3861 'strcasecmp': identifier not found alure-hrtf E:\Source\alure\examples\alure-hrtf.cpp 69 Error C3861 'strcasecmp': identifier not found alure-reverb E:\Source\alure\examples\alure-reverb.cpp 178 Error C3861 'strcasecmp': identifier not found alure-reverb E:\Source\alure\examples\alure-reverb.cpp 185 Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax alure2 e:\source\alure\src\auxeffectslot.h 31 Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax alure2_s e:\source\alure\src\auxeffectslot.h 31 Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax alure2 e:\source\alure\src\auxeffectslot.h 31 Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax alure2_s e:\source\alure\src\auxeffectslot.h 31 Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax alure2 e:\source\alure\src\auxeffectslot.h 31 Error C4576 a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax alure2_s e:\source\alure\src\auxeffectslot.h 31 Error LNK1104 cannot open file 'Debug\alure2.lib' alure-enum E:\Source\_build\alure\LINK 1 Error LNK1104 cannot open file 'Debug\alure2.lib' alure-stream E:\Source\_build\alure\LINK 1 Error LNK1104 cannot open file 'Debug\alure2.lib' alure-play E:\Source\_build\alure\LINK 1 I try to lookup the error:
      //Error: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax //Cause by code: void addSourceSend(Source source, ALuint send) { mSourceSends.emplace_back((SourceSend){source, send}); } But I can't find any clue, and the syntax of this code is really weird.
      So how can I build alure from source? Please help me
      A minor confuse about OpenAL soft
      This is a little off topic, but I can't help asking. there is the text inside the ReadMe.txt of the package: openal-soft-1.18.2-bin.zip  that I find confusing:
      I thought OpenAL soft is stand-alone package, but here is the note about OpenAL redistributable. So if I build OpenAL-soft from source, should I concern about this? And if I need, what I should do with this? My guess is: require the users to install OpenAL redistributable from Creative Labs.
       
      Thanks for reading
    • By Jan Haas
      Hello,
      I just found out about https://github.com/shader-slang/slang. It's a shader language and accompanied by a library that is supposed to make it easier to work with modular shaders.
      What do you think about that? 
      Here is the paper that describes the concept: http://graphics.cs.cmu.edu/projects/shadercomp/he17_shadercomp.pdf
      Thanks in advance
       
    • By Sanya Boyko
      Hello! I'm making the CadEditor utility. This is a universal level map editor for NES / SMD games, used to inplace change ROM files. The program has been done for a long time to edit a couple of old console games, now I have to do a little bit of updating it, perhaps turning it into a block editor, like Tiled.  
      Would anyone be interested in such a tool, or is there enough of the existing map editors functionality?
      And other question. It's possible to do export blocks from all the games already supported by the editor to tileset, and the map itself to the TMX format supported by Tiled editor, as well by many engines - so you can immediately get blocks and a game map from some old games for experiments with them into modern engines. Will anyone need this feature, if I implement it?
       
    • By Tristan Richter
      I am trying to implement status effects in my game but I have not quite been able to get the hang of it. Do you have to make a large number of classes for different kinds of status effects? Or is it possible to do it with just 1, or a small number of classes?
    • By David Burford
      Hi all, hope this is okay to post here.
      There seems to be a myriad of open source licenses these days and then multiple versions of each one so it begins to become confusing as to which you should use and when.
      My scenario is I have been working for some time on a rogueish engine that I've always intended to open source when the base engine is finished and release to whomever is interested in it. People would be welcome to use it to make their own (non-commercial) games out of it as per the norm. The engine is very modable before you even get to the source so its flexible for multiple types of project.
      To that end, in the back of my head I'm thinking one day I could REALLY polish it up and make something commercial with it as the base engine. But do I lose my right to do that if I've given away the source as "open" for other peoples non-commercial ventures? Would I be obliged to share my changes, if any, to the base engine? It seems obvious that if someone else submitted code to the open source public repository that i COULDNT use that without permission and thats fine.
      But what if someone contact me and said hey I really like the work, could I license this to do something commercial? I'm guessing I could license *my* version of the source as long as it had no one elses contributions included? This project is not in the wild yet for what its worth, I'm just trying to get a more solid understanding of what actually happens to your rights as author after you've declared "open source". 
       
      Thanks for your time! :) 
  • Popular Now