Ваш глобальный заголовочный файл должен определять имя типа без его реализации вместе с прототипами функций для создания, уничтожения и обработки данных этого типа.
header.h
#ifndef HEADER_H_
#define HEADER_H_
struct XyzData;
typedef struct XyzData XYZDATA;
typedef struct XyzData *P_XYZDATA;
P_XYZDATA CreateEmptyXyzData();
P_XYZDATA CreateFilledXyzData(int param1, int param2);
void DestroyXyzData(P_XYZDATA pData);
int ModifyXyzData(P_XYZDATA pData, int action, int param);
#endif
Затем вам нужен внутренний заголовок, который обеспечивает реализацию для структуры.
xyzintheader.h
#ifndef XYZINTHEADER_H_
#define XYZINTHEADER_H_
#include "header.h" // include the XyzData declaration
struct XyzData { // and add its definition
int par1;
int par2;
};
#endif
Тогда файлы с реализациями для определенных подпрограмм будут использовать внутренний заголовок, потому что им нужнознать детали структуры для доступа к ним.
xyzcreate.c
#include "xyzintheader.h"
#include <stdlib.h>
P_XYZDATA CreateEmptyXyzData() {
return calloc(1, sizeof(XYZDATA));
};
xyzcreatf.c
#include "xyzintheader.h"
#include <stdlib.h>
P_XYZDATA CreateFilledXyzData(int param1, int param2) {
if (P_XYZDATA pData = malloc(sizeof(XYZDATA))) {
pData->par1 = param1;
pData->par2 = param2;
return pData;
}
return NULL;
};
xyzdestr.c
#include "xyzintheader.h"
#include <stdlib.h>
void DestroyXyzData(P_XYZDATA pData) {
free(pData);
}
xyzmodif.c
#include "xyzintheader.h"
int ModifyXyzData(P_XYZDATA pData, int action, int param) {
if (! pData)
return -1;
switch (action) {
case 0:
// do something
pData->par1 = pData->par2 = 0;
return 0;
case 1:
// do something
pData->par1 += param;
pData->par2 -= param;
return 0;
}
return -2;
}
И внешние модули будут использовать открытый заголовок, потому что им нужно только знать структуру существует и какие инструменты использовать для ее обработки.
source.c
#include "header.h"
void SomeExternalLogic()
{
if (P_XYZDATA pData = CreateEmptyXyzData()) {
ModifyXyzData(pData, 0, 0);
ModifyXyzData(pData, 1, 3);
if (ModifyXyzData(pData, 13, 17) < 0)
WriteSomeErrorMessage();
DestroyXyzData(pData);
}
}