通过公共标头从私有标头导出类型

时间:2018-01-22 13:28:25

标签: c

据我了解,保护实施是一个很好的原则,因此在编写新库时,我决定试一试。我的目标是保护内部使用的数据类型,并仅导出实现我的库的人员绝对需要的数据类型。

假设我有四个文件:

library_component.c:

#include "library_component.h"

struct my_data {
    int stuff;
};

library_component.h:

// Private header
struct my_data;

LIBRARY.C

#include "library_component.h"
#include "library.h"

library.h:

// Public header
// Include guards, etc...

typedef struct my_data my_data_type;

在此示例中,library_component.clibrary.c将被编译为共享库文件library.so,并与主机内的library.h一起安装。

我不清楚的是,我应该如何处理struct my_data情况。我想将其导出为my_data_type。是否可以从公共标题中隐藏typedef语句?

2 个答案:

答案 0 :(得分:2)

如果library是唯一暴露给调用者的模块 - 它是实际的API - 那么这个设计就可以了。一个爱管闲事的来电者,由于某种原因去挖掘仅由library使用的内部头文件,但无论如何都无法用它做任何事情 - 标题中的struct my_data是一个不完整的类型。

然而,一个不那么混乱的选择可能是将library_component.h写为:

typedef struct my_data_t my_data_t;

然后在library.h中使用相同的定义 - 类型在library_component.h中声明,library.h通过#include访问它。然后一切都会清楚。在library_component.c,你会struct my_data_t { ...

最后,library.h中的所有函数都应该设计为使用my_data_t*,这是必须的,因为类型不完整,调用者将无法创建它的实例。

此设计方法称为 opaque类型 / 不透明指针

答案 1 :(得分:2)

您无法向库的用户隐藏typedef,因为这是您希望用户使用的类型。然而,这在保护私人类型方面不是问题。

typedef充当struct my_data的前瞻性声明。因此,库的用户可以创建指向该类型的指针,但不能创建该类型的实例。这保护了struct my_data

的实施细节

例如,您的库可以包含以下函数:

struct my_data *get_new();
void do_something(struct my_data *data);
void do_something_else(struct my_data *data);
void cleanup(struct my_data *data);

这些允许用户通过get_new创建结构的实例,接收指向实例的指针,并将该指针传递给其他库函数以对其进行操作。