我正在用C语言做一个大项目,我想用接口来组织它(.h)和执行(.c)文件,类似于许多面向对象的语言,如Objective-C或Java。我熟悉在C中创建静态库,但我认为在我的项目中这样做是不必要的复杂。我如何在ANSI C中实现接口/实现范例?我主要使用GCC进行编译,但我的目标是严格遵守ANSI C和交叉编译器兼容性。谢谢!
cclgggtu1#
听起来你已经在做正确的事情:好的C代码 * 还 * 在. h文件中组织接口,在. c文件中组织实现。示例a.h文件:
void f(int a);
示例a. c文件:
#include "a.h" static void helper(void) {...} void f(int a) {... use helper()...}
main. c文件示例:
#include "a.h" int main(void) { f(123); return 0; }
因为helper-function没有在头文件中声明,所以其他模块不知道它们,所以您可以获得模块性(如果你愿意的话,你可以在.c文件的顶部声明它们)。有了这种模块化,减少了需要重新编译的次数,也减少了需要重新编译的 * 量 *。(linking 每次都要做)注意,如果你没有在头文件中声明helper-functions,那么你已经很安全了。然而,在它们前面有static也在链接期间对其他模块隐藏它们,因此如果多个模块使用相同的helper-function-name,则不存在冲突。如果你只使用基本类型,那么你只需要知道这些,你可以在这里停止阅读,但是如果你的模块需要使用结构体,那么它会变得稍微复杂一些。问题示例标题b.h:
.c
static
typedef struct Obj { int data; }*Obj; Obj make(void); void work(Obj o);
你的模块想要传入和传出对象。这里的问题是,内部代码会泄露给依赖于这个头的其他模块。如果表示形式改为float data,那么所有使用的模块都必须重新编译。解决这个问题的一种方法是只使用void*。这就是很多程序所做的。然而,这很麻烦,因为每个获取void*作为参数的函数都必须将其转换为Obj。另一种方法是这样做:标题c.h:
float data
void*
Obj
typedef struct Obj*Obj; Obj make(void); void work(Obj);
实施c.c:
#include "c.h" typedef struct Obj { int data; }*Obj;
之所以这样做是因为Obj是一个指针(而不是一个通过值/复制的结构体)。其他依赖于这个模块的模块只需要知道一个指针被传入和传出,而不需要知道它指向什么。
zpjtge222#
你必须读一些关于OOP的非OOL的东西,比如http://www.cs.rit.edu/~ats/books/ooc.pdf。但是,这样做你永远不会有强大的OOP类型。
pxiryf3j3#
请帮自己一个忙,阅读C Interfaces and Implementations: Techniques for Creating Reusable Software这里是a repository of mine,它保存了一些用C编写的库,使用了书中描述的接口和实现模式。
3条答案
按热度按时间cclgggtu1#
听起来你已经在做正确的事情:好的C代码 * 还 * 在. h文件中组织接口,在. c文件中组织实现。
示例a.h文件:
示例a. c文件:
main. c文件示例:
因为helper-function没有在头文件中声明,所以其他模块不知道它们,所以您可以获得模块性(如果你愿意的话,你可以在
.c
文件的顶部声明它们)。有了这种模块化,减少了需要重新编译的次数,也减少了需要重新编译的 * 量 *。(linking 每次都要做)注意,如果你没有在头文件中声明helper-functions,那么你已经很安全了。然而,在它们前面有static
也在链接期间对其他模块隐藏它们,因此如果多个模块使用相同的helper-function-name,则不存在冲突。如果你只使用基本类型,那么你只需要知道这些,你可以在这里停止阅读,但是如果你的模块需要使用结构体,那么它会变得稍微复杂一些。
问题示例标题b.h:
你的模块想要传入和传出对象。这里的问题是,内部代码会泄露给依赖于这个头的其他模块。如果表示形式改为
float data
,那么所有使用的模块都必须重新编译。解决这个问题的一种方法是只使用void*
。这就是很多程序所做的。然而,这很麻烦,因为每个获取void*
作为参数的函数都必须将其转换为Obj
。另一种方法是这样做:标题c.h:
实施c.c:
之所以这样做是因为Obj是一个指针(而不是一个通过值/复制的结构体)。其他依赖于这个模块的模块只需要知道一个指针被传入和传出,而不需要知道它指向什么。
zpjtge222#
你必须读一些关于OOP的非OOL的东西,比如http://www.cs.rit.edu/~ats/books/ooc.pdf。但是,这样做你永远不会有强大的OOP类型。
pxiryf3j3#
请帮自己一个忙,阅读C Interfaces and Implementations: Techniques for Creating Reusable Software
这里是a repository of mine,它保存了一些用C编写的库,使用了书中描述的接口和实现模式。