我正在用C编写一个大型项目,我想使用接口(.h)和实现(.c)文件来组织它,类似于许多面向对象的语言,比如object或Java。我熟悉用C创建静态库,但我认为为我的项目创建静态库是不必要的复杂。如何在ANSI C中实现接口/实现范例?我主要使用GCC编译,但我的目标是严格遵守ANSI C和交叉编译器兼容性。谢谢!
发布于 2014-10-05 18:25:13
听起来你已经在做正确的事情了:好的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; }您获得了模块化,因为助手函数没有在头中声明,因此其他模块不知道它们(如果需要,可以在.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是一个指针(而不是值/拷贝的结构)。其他依赖于该模块的模块只需要知道指针是否被传入或传递出去,而不需要知道指针指向什么。
发布于 2014-10-05 17:50:59
您必须阅读一些关于使用非OOL的OOP的内容,如http://www.cs.rit.edu/~ats/books/ooc.pdf。但是,这样做,您将永远不会有强大的OOP类型。
发布于 2016-11-18 00:13:50
请帮你自己一个忙,看看C接口和实现:创建可重用软件的技术
下面是我的一个仓库,它保存了一些使用C语言编写的库,使用了本书中描述的接口和实现模式。
https://stackoverflow.com/questions/26205329
复制相似问题