我正在构建一个静态嵌入式C库,它有一个API头文件,列出了所有可用的功能。我不确定一些事情,我想在开始实施之前先澄清一下。
首先,由于这是一个嵌入式系统的C-Library,它有硬件FPU,我不知道应该包括什么来计算像sinf()等数学函数。通常我使用硬件特定包含,但是在这个静态C库中是不可用的,因为它可以在某些STM32或甚至某些AVR等上运行。如何解决这个问题?
进一步说我有文件foo.c和foo.h,它们在库中提供了一些隐藏的函数,然后是api.h,用户可以看到api.h,它也是隐藏的。在foo.h中现在定义了一些结构,我想在回调中返回给用户。由于这个结构是隐藏的,我不确定我应该如何处理这个回调。我应该在api.c中实现一个处理程序,它从foo.c中回调来自回调的结构,并将它们传递给用户回调,其中结构在api.h中被重新定义(具有不同的名称),或者是否存在具有较少开销的解决方案?
当我在api.h中为foo.h定义必要的结构时,我需要在foo.h中包含api.h,在api.h中也包含foo.h,这不是我认为的好主意。
对于问题的第一部分,像sinf
这样的数学运算应该由C标准库处理(您应该检查特定版本以获得对您的体系结构的支持)。然后,您可以使用math.h
头及其函数,然后编译器应使用FPU进行浮点计算。
对于第二部分,向用户显示隐藏结构的常用方法是使用foward声明,但用户必须通过指针和访问函数与结构进行交互。
举个例子,假设我们有四个文件:
api.h
:公共标题api.c
:来自公共标题的函数的源代码foo.h
:库内部标题(不会发送给最终用户)foo.c
:内部函数的源代码api.h
是那些唯一有趣的文件(没有变化)。
// file: api.h
#ifndef API_H
#define API_H
struct foo; // forward declaration of the foo structure
typedef void (*callback_t)(struct foo*); // typedef for a callback taking a
// struct foo argument
void set_callback(callback_t fn);
#endif
现在我们有一个回调类型和给回调的结构类型,但是用户不能与结构本身交互,因为编译器只知道它存在但不知道它的内容(也不知道存储大小)。
当用户像下面的代码一样编写回调时,用户需要具有一些访问功能。
#include "api.h"
void user_callback(struct foo* arg) {
// user code here
}
访问函数通常定义如下:
// in the file api.h or another header that the user has access to
int foo_get_value1(struct foo* arg);
void foo_set_value1(struct foo* arg, int new_value);
这些功能将在foo.c
中实施
struct foo {
int value1;
int value2;
};
int foo_get_value1(struct foo* arg) {
return arg->value1;
}
void foo_set_value1(struct foo* arg, int new_value) {
arg->value1 = new_value;
}
这种方法的另一个优点是,您的foo_set
函数可以进行有效性检查,以确保您的结构中具有适当的值。
请注意:我没有向我的访问函数添加任何检查以避免代码混乱,但是当将指针传递给函数时,您应该始终检查NULL