我正在研究C中的一个大项目,我想使用接口(.h)和实现(.c)文件来组织它,类似于许多面向对象的语言,如Objective-C或Java。我熟悉在C中创建静态库,但我认为对我的项目这样做是不必要的复杂。如何在ANSI C中实现接口/实现范例?我主要使用GCC进行编译,但我的目标是严格遵守ANSI C和交叉编译器的兼容性。谢谢!
答案 0 :(得分:7)
听起来你已经正在做正确的事:好的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-functions没有在头文件中声明,因此其他模块不了解它们(如果需要,可以在.c
文件的顶部声明它们)。具有此模块性可减少所需的重新编译次数,并减少必须重新编译的。 (链接必须每次都完成)。请注意,如果您没有在标头中声明辅助函数,那么您已经非常安全了,但是在它们前面有static
也会在链接期间将它们隐藏在其他模块中,因此如果多个模块使用相同的辅助函数名称。
如果你只使用原始类型,那么这就是你需要知道的所有内容,你可以在这里停止阅读。但是,如果您的模块需要使用结构,那么它会变得更复杂。
有问题的示例标题b.h:
typedef struct Obj {
int data;
}*Obj;
Obj make(void);
void work(Obj o);
您的模块想要传入和传出对象。这里的问题是,内部泄漏到依赖于此标头的其他模块。如果表示更改为float data
,那么所有使用模块都必须重新编译。解决此问题的一种方法是仅使用void*
。这就是有多少程序。然而,这很麻烦,因为将void*
作为参数的每个函数都必须将其强制转换为Obj
。另一种方法是这样做:
标题c.h:
typedef struct Obj*Obj;
Obj make(void);
void work(Obj);
实施c.c:
#include "c.h"
typedef struct Obj {
int data;
}*Obj;
这个工作的原因是,Obj是一个指针(与value / copy的结构相反)。依赖于此模块的其他模块只需要知道指针正在传入和传出,而不是指向它。
答案 1 :(得分:0)
您必须阅读有关非OOL的OOP,例如http://www.cs.rit.edu/~ats/books/ooc.pdf。 但是,这样做你永远不会有强大的OOP输入。
答案 2 :(得分:0)
请帮自己一个忙,并阅读C Interfaces and Implementations: Techniques for Creating Reusable Software
这里是a repository of mine,它使用接口模式来保存一些用C语言编写的库。本书中描述的实现。