使用 headers 实现(通用,非 C++)interface-like 行为
Implenting (generic, not C++)interface-like behaviour with headers
我正在尝试在(嵌入式)C 上下文中创建某种代码上层结构,这将允许我在保留某个已定义接口的同时换入和换出代码本身的底层实现。我不确定如何最好地描述我正在尝试做的事情,所以我将举一个小例子:
interface.h:
(#pragma once or other include guard scheme)
/**
* 'Standard' include file, implementation
* independent. Mostly contains
* Declarations, specifying function name,
* return values, parameters, types, etc.
*/
static void do_something(void);
static void do_something_else(void);
//Subsequently includes the actual header for the
//specific implementation to be used
#include "implementation.h"
implementation.h:
(#pragma once or other include guard scheme)
/**
* Include file, implementation specific.
* Mostly contains implementation specific
* defines. The function prototypes are
* obtained from the interface.h include.
* However, some implementations need to be
* static inline for performance issues, and
* are defined here.
*/
static inline void do_something(void) {
implementation_of_something;
}
implementation.c:
#include "interface.h"
#include "implementation.h"
/**
* Actual implementations of the rest of the
* functions.
*/
static void do_something_else(void) {
implementation_of_something_else;
}
最后,user.c:
#include interface.h
int main(void){
do_something();
do_something_else();
}
期望的结果是,当编译 main.c 并链接可执行文件时,do_something()
调用内联到 main()
,而 do_something_else()
导致 implementation.o 正在链接并进行函数调用。
在很大程度上,这似乎行得通。
不过,我的问题如下:
- 这是一种可以接受的做事方式吗?有没有更好的方法来做到这一点?还有其他更合适的模式吗?
- 不同地方函数原型不同。具体针对
do_something()
的情况,一种是static void
,另一种是static inline void
。 Doxygen
当然似乎对此有一些问题,我不确定编译器是否有问题。它有任何后果吗?有没有办法避免这种情况?
编辑:补充问题:
- 如果在翻译单元中发现以下内容,编译器将如何处理:
案例一:
extern void function(void); (from interface.h)
static inline void function(void){ (from implementation.h)
function_body;
}
function(); (from user.c)
从你的 post 中不清楚是否 实现(通用的,不是 C++)interface-like 行为 headers 是一项要求。如果不是,我会稍微改变策略。
interface.h:
使函数 extern
而不是 static
。
extern void do_something(void);
extern void do_something_else(void);
interface.c:
根据 implementation.h
中提供的实现来实现 intereface.h
中声明的函数。
#include "interface.h"
#include "implementation.h"
static void do_something(void) {
implementation_of_something();
}
static void do_something_else(void) {
imlementation_of_something_else();
}
implementation.h:
使实现函数也extern
而不是static
。
extern void implementation_of_something(void);
extern void imlementation_of_something_else(void);
implementation.c:
函数的实际实现。
#include "implementation.h"
void implementation_of_something(void) {
//... The implementation
}
void implementation_of_something_else(void) {
//... The implementation
}
user.c:
#include "interface.h"
int main(void){
do_something();
do_something_else();
}
此更改减少了 implementation.h
对一个文件的依赖。如果交换实现,则不必重新编译依赖于 interface.h
的 .c 文件。
函数指针用于将 OO 带入 C 世界。想法是有一个单一的功能,如:
do(function pointer to desired implementation){
...
}
所以在你的主程序中你只调用 do(),但根据情况,传递给它的参数——这里是指向实现它的函数的指针——是不同的。面向对象搜索函数指针,这是一种惯例。
我正在尝试在(嵌入式)C 上下文中创建某种代码上层结构,这将允许我在保留某个已定义接口的同时换入和换出代码本身的底层实现。我不确定如何最好地描述我正在尝试做的事情,所以我将举一个小例子:
interface.h:
(#pragma once or other include guard scheme)
/**
* 'Standard' include file, implementation
* independent. Mostly contains
* Declarations, specifying function name,
* return values, parameters, types, etc.
*/
static void do_something(void);
static void do_something_else(void);
//Subsequently includes the actual header for the
//specific implementation to be used
#include "implementation.h"
implementation.h:
(#pragma once or other include guard scheme)
/**
* Include file, implementation specific.
* Mostly contains implementation specific
* defines. The function prototypes are
* obtained from the interface.h include.
* However, some implementations need to be
* static inline for performance issues, and
* are defined here.
*/
static inline void do_something(void) {
implementation_of_something;
}
implementation.c:
#include "interface.h"
#include "implementation.h"
/**
* Actual implementations of the rest of the
* functions.
*/
static void do_something_else(void) {
implementation_of_something_else;
}
最后,user.c:
#include interface.h
int main(void){
do_something();
do_something_else();
}
期望的结果是,当编译 main.c 并链接可执行文件时,do_something()
调用内联到 main()
,而 do_something_else()
导致 implementation.o 正在链接并进行函数调用。
在很大程度上,这似乎行得通。
不过,我的问题如下:
- 这是一种可以接受的做事方式吗?有没有更好的方法来做到这一点?还有其他更合适的模式吗?
- 不同地方函数原型不同。具体针对
do_something()
的情况,一种是static void
,另一种是static inline void
。Doxygen
当然似乎对此有一些问题,我不确定编译器是否有问题。它有任何后果吗?有没有办法避免这种情况?
编辑:补充问题:
- 如果在翻译单元中发现以下内容,编译器将如何处理:
案例一:
extern void function(void); (from interface.h)
static inline void function(void){ (from implementation.h)
function_body;
}
function(); (from user.c)
从你的 post 中不清楚是否 实现(通用的,不是 C++)interface-like 行为 headers 是一项要求。如果不是,我会稍微改变策略。
interface.h:
使函数 extern
而不是 static
。
extern void do_something(void);
extern void do_something_else(void);
interface.c:
根据 implementation.h
中提供的实现来实现 intereface.h
中声明的函数。
#include "interface.h"
#include "implementation.h"
static void do_something(void) {
implementation_of_something();
}
static void do_something_else(void) {
imlementation_of_something_else();
}
implementation.h:
使实现函数也extern
而不是static
。
extern void implementation_of_something(void);
extern void imlementation_of_something_else(void);
implementation.c:
函数的实际实现。
#include "implementation.h"
void implementation_of_something(void) {
//... The implementation
}
void implementation_of_something_else(void) {
//... The implementation
}
user.c:
#include "interface.h"
int main(void){
do_something();
do_something_else();
}
此更改减少了 implementation.h
对一个文件的依赖。如果交换实现,则不必重新编译依赖于 interface.h
的 .c 文件。
函数指针用于将 OO 带入 C 世界。想法是有一个单一的功能,如:
do(function pointer to desired implementation){
...
}
所以在你的主程序中你只调用 do(),但根据情况,传递给它的参数——这里是指向实现它的函数的指针——是不同的。面向对象搜索函数指针,这是一种惯例。