0

I am building a c++ library and I would need to initialize an openGL context for my program ( and other default resource objects ). Would it be good practice ( considering modern c++ semantics ) to "hide the Init. code" in a code chunk being called before main ? I cannot use static variables because I need to initialize things in a specific order ! (I cannot init a texture before openGLm or SDL !)

Here is my code :

#include <stdio.h>

#ifdef _MSC_VER // For msvc / msvc++ 2015

#define CCALL __cdecl
#pragma section(".CRT$XCU",read)
#define INITIALIZER(f) \
   static void __cdecl f(void); \
   __declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
   static void __cdecl f(void)

#elif defined(__GNUC__) for gcc / g++

#define CCALL
#define INITIALIZER(f) \
   static void f(void) __attribute__((constructor)); \
   static void f(void)

#endif

static void CCALL finalize(void)
{
    /* Some king of delete / dispose here : like SDL_Quit, ... */
}

INITIALIZER(initialize)
{
/* 
   HERE IS THE STARTUP CODE ...

*/

}
Coder32
  • 181
  • 1
  • 10
  • 2
    @ray Static objects constructors _are called_ before main. – user58697 Oct 27 '15 at 18:10
  • @ray Functions CAN be called in the process of initialising global variables and static members. – Jon Trauntvein Oct 27 '15 at 18:10
  • @ray [Are you sure?](http://stackoverflow.com/questions/4783404/is-main-really-start-of-a-c-program) – aslg Oct 27 '15 at 18:14
  • I have no idea what those macros are doing. I would just call a setup function first thing in main, or use singletons if you must. You can make singletons setup in the desired order. – Neil Kirk Oct 27 '15 at 19:40
  • If you had a single static variable that instantiated a single class, you could put all your initialization into that class and have complete control over initialization order. You just can't control when that class is initialized in relation to other static storage. – Steve Oct 27 '15 at 20:13
  • @user58697: I've removed the inaccurate comment. I think I could've worded the first part better. I misunderstood OP and thought (s)he was trying to "hide" exec'ing code through preprocessor 'magic'. – code_dredd Oct 27 '15 at 21:53

3 Answers3

3

Would it be good practice ( considering modern c++ semantics ) to "hide the Init. code" in a code chunk being called before main ?

Because order of initialization of global static objects is not guaranteed I would consider such practice as bad in general. Another reason - providing diagnostics for such code is not trivial and creates artificial problems that can be easily avoided without using this method. There are exceptions but they are rare, definetly not as many to consider this as a good practice.

Slava
  • 43,454
  • 1
  • 47
  • 90
  • I agree. This can create very subtle and hard to debug problems. You're much better off explicitly controlling what happens by calling functions in the order you want them to happen. – David Schwartz Oct 27 '15 at 19:45
2

Would it be good practice ( considering modern c++ semantics ) to "hide the Init. code" in a code chunk being called before main ?

Only way to run anything before main is to do it in the constructor of a static object.

I cannot use static variables

You've ran out of options. There is no way to achieve what you're asking for in standard c++.

To answer the question of would it be good practice... that's opinion based, but I'll say that I would usually consider it bad if a library initializes something before I've explicitly told it to initialize. That would prevent the user of the library from controlling the order of initialization of your library in relation to other libraries. It's especially important when your library depends on other libraries like SDL.

eerorika
  • 232,697
  • 12
  • 197
  • 326
2

The standard, section 3.6.2, says that non-local static variables may be initialized before the first statement of main:

It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of main.

Thus, it doesn't say they must be initialized before the first statement of main. There is no way in C++ to enforce a constraint that anything would be initialized before main() is called, except for static variables defined in the same compilation unit as main.

The best solution is simply to include your resource management within main itself:

int main()
{
    // Load resources (housekeeping code)

    // Do real work (applicative code)

    // Release resources (housekeeping code)
}

If you want to separate the applicative code from the housekeeping code, a commonly used approach is to use inversion of control (sometimes via a template method pattern):

  • A separate function or method is dedicated to the applicative or user code
  • The function main is responsible both for doing the housekeeping and for invoking the user-code or applicative-code function or method.

This is exemplified below:

// The function below is expected to exist by the framework
// It must be implemented by the user
int userMain()
{
    // Implement user-code here
}

// The code below is implemented by the framework
// It expects the user to have implemented a function userMain
int main()
{
    FrameWorkData theFrameWorkData;

    // The framework performs its initialization house-keeping here
    theFrameWorkData.initialize();

    // The framework invokes the user-code (inversion of control)
    userMain();

    // The framework performs its clean-up house-keeping here
    theFrameWorkData.cleanup();
}
Daniel Strul
  • 1,458
  • 8
  • 16
  • what do you mean by "auxiliary main" ? Something like redefining main like SDL did with SDL_main ? – Coder32 Oct 27 '15 at 18:36
  • Yes, except that I got my example backwards here (I'll correct that). The SDL designers obviously needed to make sure that the users would let the SDL run-time do its housekeeping before using SDL fonctions. So the true application entry-point, `WinMain`, is managed by the SDL framework and invokes the entry point of the user code, `SDL_main`. More details are available here: http://stackoverflow.com/a/11976179/5482150 – Daniel Strul Oct 27 '15 at 19:20
  • Thank you for your help : ) – Coder32 Oct 27 '15 at 20:36