如何跨多个翻译单元共享opaque类型?

St.*_*rio 0 c linux struct

我正在开发自己的C项目,需要一些design/common_C_idiom建议.我试图解决的问题是打开已配置设备的输入日期流.但我想保持配置和设备分离.这是我尝试过的:

  1. 组态:

config.h

#ifndef CONFIG_H
#define CONFIG_H

typedef struct config_t config_t;

config_t* config_t_allocate(void);
void config_t_free(config_t *);
//functions to set configuration parameters

#endif //CONFIG_H
Run Code Online (Sandbox Code Playgroud)

config.c

#include <stdlib.h>
#include "device.h"

struct config_t{
    const char * name;
};

config_t* config_t_allocate(void){
    return malloc(sizeof(config_t));
}

void config_t_free(config_t * config_ptr){
    free(config_ptr);
}
Run Code Online (Sandbox Code Playgroud)
  1. 设备:

device.h

#ifndef DEVICE_H
#define DEVICE_H

typedef struct config_t config_t;

typedef struct device_t device_t;

void configure_device(device_t**, config_t*);

//other device-related methods

#endif //DEVICE_H
Run Code Online (Sandbox Code Playgroud)

device.c

#include "device.h"
#include <sys/fcntl.h>

struct device_t{
    int fd;
};

//Does not compile. What is the confit_t type?
void configure_device(device_t** device, config_t* config_ptr){
    *device = malloc(sizeof(**device));
    (*device) -> fd = open(config_ptr -> name, O_RDONLY);
}
Run Code Online (Sandbox Code Playgroud)

所以我想分享在多个翻译单元中config_t完成的类型config.c.我唯一能想到的是创建一个包含struct 的"私有"头文件.像这样的东西: types/configdef.h

#ifndef TYPES_CONFIG_DEF_H
#define TYPES_CONFIG_DEF_H

struct config_t{
    const char * name;
};

#endif //TYPES_CONFIG_DEF_H
Run Code Online (Sandbox Code Playgroud)

并将其包含在我需要的任何地方config_t.

Jon*_*ler 5

如果您使用类似的opaque类型config_t,则放弃直接在源代码中访问其成员的选项,该源代码不了解实现细节.但是,您可以提供执行此操作的功能:

extern const char *config_t_get_name(config_t *config);
Run Code Online (Sandbox Code Playgroud)

或其左右,声明config.h,定义config.c,用于device.c.

但是如何放入struct config_t{ const char * name; };一些我不会暴露的头文件(类库私有)并在实现C文件中的任何地方使用它.是不常见还是有缺点?

实际上,访问函数的主要替代方法是"私有"标题,但这通常不如访问函数.可以办到; 它并不完全不常见,特别是如果需要访问结构内部的函数套件太大而无法合理地放在单个源文件中(或者因为本地规则是'每个源文件一个非静态函数',或者...).因此,困难在于确保不应该(不)使用它的文件不应该(不)使用它.这表明私有标头不应与库一起安装,并且私有标头可能位于与项目的公共标头不同的目录中.

考虑一下你是否应该强制执行:

 #include "project/headerX.h"             // General, public headers for the project
 #include "project/private/internal.h"    // Private headers for limited use
Run Code Online (Sandbox Code Playgroud)

然后,您可以通过使用grep或等效查找不应被允许的引用来监管私有标头的使用,等等.或者,或者可能结合使用,为私有标头使用独特的命名方案,使用pvt_前缀来表示"私有":

#include "project/internal/pvt_config.h"
Run Code Online (Sandbox Code Playgroud)

这个主题有无穷无尽的变化.程序员将设计各种方案来访问私有头文件以利用它们.最终,您必须相信程序员遵守规则 - 除了明确授予使用权限的文件外,您不得使用私有标头.如果他们不能接受这种纪律,也许他们毕竟不应该参与这个项目.或许你应该花些时间来理解为什么顽固的程序员不能使用你提供的访问功能 - 设计有什么问题吗?

您可以在Google(或您选择的搜索引擎)上搜索' getters setters'; 结果似乎是有益的.添加您选择的语言(C++,Java,JavaScript图显着; C不是那么突出,但它确实提取了可能有用的参考文献).

  • 一个技巧是包括来自h文件的公共头文件和来自c文件的私有头文件.这样您就可以阻止该私有标头的内容传播到其他翻译单元. (3认同)