是否可以将几个不同的函数声明指向一个函数定义
Is it possible to point several different function declarations into a single function definition
比如说,我有几个函数声明,它们应该在多个库文件中执行类似的操作:
// file0.h
void delay_ms0(unsigned int);
// file1.h
void delay_ms1(int);
// file2.h
extern void delay_ms2(int);
// file3.h
int delay_ms3(unsigned int);
// file4.h
void delay_ms4(unsigned char);
// file5.h
void delay_us(unsigned long long);
// file6.h
void delay_ms6(const int *);
// file7.h
// (in some cases, structs used to pass several functions)
typedef void (*const delay_fptr_t)(int);
extern delay_fptr_t delay_ms7;
在我的主应用程序中,我有针对特定平台实现的实际定义:
// main.c
void delay_ms(unsigned int time_ms) { platform_shutdown(time_ms*128); };
所以,问题是:是否有可能在不使用已编译程序中的附加指令的情况下将它们中的一些或全部指向相同的实现,即以某种方式指示编译器或链接器将函数调用发送到哪里。特别是说到海湾合作委员会。
如果是,开发集成库会更方便...
目前,标准解决方案通常看起来像这样:
// main.c
// these are extra function calls, and not always optimized out. Consumes both RAM and ROM.
void delay_ms0(unsigned int val) { delay_ms(val); };
void delay_ms1(int val) { delay_ms((unsigned int) val); };
// Somehow not always linked properly, so when called at runtime, causes hardfaults, or just nothing happens
inline void delay2(int val) { delay_ms((unsigned int) val); };
// most probably there is no way around that, as we have to return something
int delay_ms3(unsigned int) { delay_ms((unsigned int) val); return 0; };
// most probably there is no way around that, as 'c_val' has to be expanded
void delay_ms4(unsigned char c_val) { delay_ms((unsigned int) c_val); };
// most probably there is no way around that, as 'll_val' has to be processed before passing further
void delay_us(unsigned long long ll_val) { delay_ms((unsigned int) ll_val/1000); };
// most probably there is no way around that, as 'p_val' has to be dereferenced
void delay_ms6(const int *p_val) { delay_ms((unsigned int) *p_val); };
// this is my favorite so far, as it does not use extra RAM and allows some slack, when function definitions do not exactly match, but it certainly does use ROM to store pointers
delay_fptr_t delay_ms7 = (delay_fptr_t)delay_ms;
// I would like to see something like that^, but for standard declarations
// I.e. are there any alternatives to:
void (*delay2_ms)(int) = delay_ms; // gcc error: 'delay2_ms' redeclared as different kind of symbol
是的,这是可能的。直接的方法是使用 alias
属性(参见 GCC docs)。一个小例子:
int some(int x) {
return 2*x;
}
int more(int y) __attribute__((alias("some")));
现在,some
和more
是同一个函数。
但请注意,您必须确保调用约定相同。这应该是非常明显的,否则 必须 是一些转换代码(仍然,在许多情况下,包装器归结为一些以 JMP
[或等价物;除非您调整 return 值或类似],否则不应增加用于 link 合并库的蹦床。
不过,如果你真的关心性能,你可以考虑使用link时间优化。现在由 GCC 支持;在 the docs 中搜索 -flto
。 (简而言之:在编译和 linking 时将 -flto
传递给 GCC)
比如说,我有几个函数声明,它们应该在多个库文件中执行类似的操作:
// file0.h
void delay_ms0(unsigned int);
// file1.h
void delay_ms1(int);
// file2.h
extern void delay_ms2(int);
// file3.h
int delay_ms3(unsigned int);
// file4.h
void delay_ms4(unsigned char);
// file5.h
void delay_us(unsigned long long);
// file6.h
void delay_ms6(const int *);
// file7.h
// (in some cases, structs used to pass several functions)
typedef void (*const delay_fptr_t)(int);
extern delay_fptr_t delay_ms7;
在我的主应用程序中,我有针对特定平台实现的实际定义:
// main.c
void delay_ms(unsigned int time_ms) { platform_shutdown(time_ms*128); };
所以,问题是:是否有可能在不使用已编译程序中的附加指令的情况下将它们中的一些或全部指向相同的实现,即以某种方式指示编译器或链接器将函数调用发送到哪里。特别是说到海湾合作委员会。 如果是,开发集成库会更方便...
目前,标准解决方案通常看起来像这样:
// main.c
// these are extra function calls, and not always optimized out. Consumes both RAM and ROM.
void delay_ms0(unsigned int val) { delay_ms(val); };
void delay_ms1(int val) { delay_ms((unsigned int) val); };
// Somehow not always linked properly, so when called at runtime, causes hardfaults, or just nothing happens
inline void delay2(int val) { delay_ms((unsigned int) val); };
// most probably there is no way around that, as we have to return something
int delay_ms3(unsigned int) { delay_ms((unsigned int) val); return 0; };
// most probably there is no way around that, as 'c_val' has to be expanded
void delay_ms4(unsigned char c_val) { delay_ms((unsigned int) c_val); };
// most probably there is no way around that, as 'll_val' has to be processed before passing further
void delay_us(unsigned long long ll_val) { delay_ms((unsigned int) ll_val/1000); };
// most probably there is no way around that, as 'p_val' has to be dereferenced
void delay_ms6(const int *p_val) { delay_ms((unsigned int) *p_val); };
// this is my favorite so far, as it does not use extra RAM and allows some slack, when function definitions do not exactly match, but it certainly does use ROM to store pointers
delay_fptr_t delay_ms7 = (delay_fptr_t)delay_ms;
// I would like to see something like that^, but for standard declarations
// I.e. are there any alternatives to:
void (*delay2_ms)(int) = delay_ms; // gcc error: 'delay2_ms' redeclared as different kind of symbol
是的,这是可能的。直接的方法是使用 alias
属性(参见 GCC docs)。一个小例子:
int some(int x) {
return 2*x;
}
int more(int y) __attribute__((alias("some")));
现在,some
和more
是同一个函数。
但请注意,您必须确保调用约定相同。这应该是非常明显的,否则 必须 是一些转换代码(仍然,在许多情况下,包装器归结为一些以 JMP
[或等价物;除非您调整 return 值或类似],否则不应增加用于 link 合并库的蹦床。
不过,如果你真的关心性能,你可以考虑使用link时间优化。现在由 GCC 支持;在 the docs 中搜索 -flto
。 (简而言之:在编译和 linking 时将 -flto
传递给 GCC)