Miam-Player  0.8.0
A nice music player
prepost.h
Go to the documentation of this file.
1 /******************************************************************************
2  prepost.h: Add function calls before/after main()
3  Copyright (C) 2012-2013 Wang Bin <wbsecg1@gmail.com>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 ******************************************************************************/
19 
20 #ifndef PREPOST_H
21 #define PREPOST_H
22 
23 /*Avoid a compiler warning when the arguments is empty,
24  *e.g. PRE_FUNC_ADD(foo). The right one is PRE_FUNC_ADD(f,)*/
25 
26 /*
27  * TODO:
28  * boost::call_once
29  * http://stackoverflow.com/questions/4173384/how-to-make-sure-a-function-is-only-called-once
30  * http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fco.htm
31  */
32 #ifdef __cplusplus
33 /* for C++, we use non-local static object to call the functions automatically before main().
34  * anonymous namespace: avoid name confliction('static' keyword is not necessary)
35  *
36  */
37 #define PRE_FUNC_ADD(f, .../*args*/) \
38  namespace { \
39  static const struct initializer_for_##f { \
40  inline initializer_for_##f() { \
41  f(__VA_ARGS__); \
42  } \
43  } __sInit_##f; \
44  }
45 
46 #define POST_FUNC_ADD(f, .../*args*/) \
47  namespace { \
48  static const struct deinitializer_for_##f { \
49  inline deinitializer_for_##f() {} \
50  inline ~deinitializer_for_##f() { f(__VA_ARGS__); } \
51  } __sDeinit_##f; \
52  }
53 
54 #else /*for C. ! defined __cplusplus*/
55 /*
56  *http://buliedian.iteye.com/blog/1069072
57  *http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/_crt.c.htm
58  */
59 #if defined(_MSC_VER)
60 #pragma section(".CRT$XIU", long, read)
61 #pragma section(".CRT$XPU", long, read)
62 #define _CRTALLOC(x) __declspec(allocate(x))
63 
64 /*TODO: Auto unique naming*/
65 typedef int (__cdecl *_PF)(); /* why not void? */
66 /*static to avoid multiple defination*/
67 #define PRE_FUNC_ADD(f, .../*args*/) \
68  static int init_##f() { f(__VA_ARGS__); return 0;} \
69  _CRTALLOC(".CRT$XIU") static _PF pinit_##f [] = { init_##f }; /*static void (*pinit_##f)() = init_##f //__cdecl */
70 #define POST_FUNC_ADD(f, .../*args*/) \
71  static int deinit_##f() { f(__VA_ARGS__); return 0;} \
72  _CRTALLOC(".CRT$XPU") static _PF pdeinit_##f [] = { deinit_##f };
73 #elif defined(__GNUC__)
74 #define PRE_FUNC_ADD(f, ...) \
75  __attribute__((constructor)) static void init_##f() { f(__VA_ARGS__); }
76 #define POST_FUNC_ADD(f, ...) \
77  __attribute__((destructor)) static void deinit_##f() { f(__VA_ARGS__); }
78 
79 #else
80 #ifndef __cplusplus
81 #error Not supported for C: PRE_FUNC_ADD, POST_FUNC_ADD
82 #endif
83 #include <stdlib.h>
84 /*static var init, atexit*/
85 #define PRE_FUNC_ADD(f, ...) \
86  static int init_##f() { f(__VA_ARGS__); return 0; } \
87  static int v_init_##f = init_##f();
88 /*Works for C++. For C, gcc will throw an error:
89  *initializer element is not constant */
90 /*atexit do not support arguments*/
91 #define POST_FUNC_ADD(f, ...) \
92  static void atexit_##f() { atexit(f); } \
93  PRE_FUNC_ADD(atexit_##f)
94 #endif
95 #endif //__cplusplus
96 #endif // PREPOST_H