Как разделить непрозрачный тип на несколько единиц перевода? - PullRequest
0 голосов
/ 27 ноября 2018

Я работаю над своим собственным C-проектом и мне нужен совет по дизайну / 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

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);
}
Устройство:

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

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);
}

Итак, я хотел бы поделиться типом config_t выполненов config.c через несколько единиц перевода.Единственное, что я могу себе представить, это создать "приватный" заголовочный файл со структурой.Примерно так: types/configdef.h

#ifndef TYPES_CONFIG_DEF_H
#define TYPES_CONFIG_DEF_H

struct config_t{
    const char * name;
};

#endif //TYPES_CONFIG_DEF_H

И включать его везде, где мне нужно config_t.

1 Ответ

0 голосов
/ 27 ноября 2018

Если вы используете непрозрачный тип, такой как config_t, вы отказываетесь от возможности доступа к его элементам непосредственно в исходном коде, который не относится к деталям реализации.Вы можете предоставить функцию для этого, хотя:

extern const char *config_t_get_name(config_t *config);

или около того, объявленную в 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

После этого вы можете контролировать использование частных заголовков, используя grep или эквивалентный для поиска ссылок, которые не должны быть разрешены, и т. Д. В качестве альтернативы или, возможно, совместно, используйте отличительную схему именования для частных заголовковиспользуя префикс pvt_ для обозначения «приватный»:

#include "project/internal/pvt_config.h"

Существует бесконечная вариация темы.Программисты разработают все виды схем, чтобы получить доступ к частным заголовкам, чтобы использовать их.В конечном счете, вы должны доверять своим программистам, чтобы они следовали правилам - вы не должны использовать частные заголовки, за исключением файлов, явно предоставивших разрешение на их использование.Если они не могут принять эту дисциплину, возможно, им вообще не следует участвовать в проекте.Или, может быть, вам нужно время, чтобы понять, почему непокорные программисты не могут использовать предоставляемые вами функции доступа - что-то не так с дизайном?

Вы можете выполнить поиск в Google (или в выбранной вами поисковой системе) для 'getters setters ';результаты кажутся информативными.Добавьте ваш язык по выбору (C ++, Java, JavaScript заметно; C не так заметно, но он вызывает ссылки, которые, вероятно, будут полезны).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...