据我了解,保护实施是一个很好的原则,因此在编写新库时,我决定试一试。我的目标是保护内部使用的数据类型,并仅导出实现我的库的人员绝对需要的数据类型。
假设我有四个文件:
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.c
和library.c
将被编译为共享库文件library.so
,并与主机内的library.h
一起安装。
我不清楚的是,我应该如何处理struct my_data
情况。我想将其导出为my_data_type
。是否可以从公共标题中隐藏typedef语句?
答案 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
创建结构的实例,接收指向实例的指针,并将该指针传递给其他库函数以对其进行操作。