见:haproxy代码
C语言注册函数和调用函数,便于模块化开发和编程。
#include
#ifdef __APPLE__
#define HA_SECTION(s) __attribute__((__section__("__DATA, " s)))
#define HA_SECTION_START(s) __asm("section$start$__DATA$" s)
#define HA_SECTION_STOP(s) __asm("section$end$__DATA$" s)
#else
#define HA_SECTION(s) __attribute__((__section__(s)))
#define HA_SECTION_START(s)
#define HA_SECTION_STOP(s)
#endif
/*
* Please keep those names short enough, they are used to generate section
* names, Mac OS X accepts section names up to 16 characters, and we prefix
* them with i_, so stage name can't be more than 14 characters.
*/
enum init_stage {
STG_PREPARE = 0, // preset variables, tables, list heads
STG_LOCK, // pre-initialize locks
STG_REGISTER, // register static lists (keywords etc)
STG_ALLOC, // allocate required structures
STG_POOL, // create pools
STG_INIT, // subsystems normal initialization
STG_SIZE // size of the stages array, must be last
};
/* This is the descriptor for an initcall */
struct initcall {
void (*const fct)(void *arg1, void *arg2, void *arg3);
void *arg1;
void *arg2;
void *arg3;
#if defined(USE_OBSOLETE_LINKER)
void *next;
#endif
};
/* declare a symbol as global */
#define __HA_GLOBL(sym) __asm__(".globl " #sym)
#define HA_GLOBL(sym) __HA_GLOBL(sym)
#define HA_INIT_SECTION(s) HA_SECTION("i_" # s)
#define __DECLARE_INITCALL(stg, linenum, function, a1, a2, a3) \
HA_GLOBL(__start_i_##stg ); \
HA_GLOBL(__stop_i_##stg ); \
static const struct initcall *__initcb_##linenum \
__attribute__((__used__)) HA_INIT_SECTION(stg) = \
(stg < STG_SIZE) ? &(const struct initcall) { \
.fct = (void (*)(void *,void *,void *))function, \
.arg1 = (void *)(a1), \
.arg2 = (void *)(a2), \
.arg3 = (void *)(a3), \
} : NULL
#define _DECLARE_INITCALL(...) \
__DECLARE_INITCALL(__VA_ARGS__)
#define INITCALL0(stage, function) \
_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
/* Declare func */
#define DECLARE_INIT_SECTION(stg) \
extern __attribute__((__weak__)) const struct initcall *__start_i_##stg HA_SECTION_START("i_" # stg); \
extern __attribute__((__weak__)) const struct initcall *__stop_i_##stg HA_SECTION_STOP("i_" # stg)
#define FOREACH_INITCALL(p,stg) \
for ((p) = &(__start_i_##stg); (p) < &(__stop_i_##stg); (p)++)
#define RUN_INITCALLS(stg) \
do { \
const struct initcall **ptr; \
if (stg >= STG_SIZE) \
break; \
FOREACH_INITCALL(ptr, stg) \
(*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
} while (0)
/* register func1 */
static void _do_register_func1(void)
{
printf("TEST: _do_register_func1()\n");
}
#if 0
__asm__(".globl " "__start_i_STG_REGISTER");
__asm__(".globl " "__stop_i_STG_REGISTER");
static const struct initcall *__initcb_405 __attribute__((__used__)) __attribute__((__section__("i_" "STG_REGISTER"))) = (STG_REGISTER < STG_SIZE) ? &(const struct initcall)
{
.fct = (void (*)(void *,void *,void *))_do_register,
.arg1 = (void *)(0),
.arg2 = (void *)(0),
.arg3 = (void *)(0),
} : ((void *)0);
#endif
INITCALL0(STG_REGISTER, _do_register_func1);
/* register func2 */
static void _do_register_func2(void)
{
printf("TEST: _do_register_func2()\n");
}
INITCALL0(STG_REGISTER, _do_register_func2);
/* register func3 */
static void _do_register_func3(void)
{
printf("TEST: _do_register_func3()\n");
}
INITCALL0(STG_REGISTER, _do_register_func3);
/* declare func1, func2, func3 */
DECLARE_INIT_SECTION(STG_REGISTER);
int main(int argc, char *const argv[])
{
/* call func1, func2, func3 */
RUN_INITCALLS(STG_REGISTER);
printf("hello world\n");
return 0;
}
编译和运行:
ubuntu@dev:test-06$ gcc test1.c
ubuntu@dev:test-06$ ./a.out
TEST: _do_register_func1()
TEST: _do_register_func2()
TEST: _do_register_func3()
hello world
不使用__attribute__((used)) 和 attribute((section(““ ““)))
#include
/* register func1 */
static void _do_register_func1(void)
{
printf("TEST: _do_register_func1()\n");
}
/* register func2 */
static void _do_register_func2(void)
{
printf("TEST: _do_register_func2()\n");
}
/* register func3 */
static void _do_register_func3(void)
{
printf("TEST: _do_register_func3()\n");
}
int main(int argc, char *const argv[])
{
/* call func1, func2, func3 */
_do_register_func1();
_do_register_func2();
_do_register_func3();
printf("hello world\n");
return 0;
}