ANSI C中的接口/实现

zbdgwd5y  于 2023-03-28  发布在  其他
关注(0)|答案(3)|浏览(153)

我正在用C语言做一个大项目,我想用接口来组织它(.h)和执行(.c)文件,类似于许多面向对象的语言,如Objective-C或Java。我熟悉在C中创建静态库,但我认为在我的项目中这样做是不必要的复杂。我如何在ANSI C中实现接口/实现范例?我主要使用GCC进行编译,但我的目标是严格遵守ANSI C和交叉编译器兼容性。谢谢!

cclgggtu

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:

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是一个指针(而不是一个通过值/复制的结构体)。其他依赖于这个模块的模块只需要知道一个指针被传入和传出,而不需要知道它指向什么。

zpjtge22

zpjtge222#

你必须读一些关于OOP的非OOL的东西,比如http://www.cs.rit.edu/~ats/books/ooc.pdf。但是,这样做你永远不会有强大的OOP类型。

pxiryf3j

pxiryf3j3#

请帮自己一个忙,阅读C Interfaces and Implementations: Techniques for Creating Reusable Software
这里是a repository of mine,它保存了一些用C编写的库,使用了书中描述的接口和实现模式。

相关问题