Мне кажется, что у вас есть два противоречивых требования.
Вы хотите, чтобы пользователь выделил память для internal_buffer
(и, я полагаю, также обновите internal_buffer_size
).
Вы хотите скрыть internal_buffer
от пользователя.
Вы не можете сделать оба! Если пользователь собирается обрабатывать выделение памяти, вы не можете «спрятать» буфер. Так что либо вы должны признать, что пользователь знает о буфере, либо вы должны выделить память в вашем коде.
Хорошо известным способом скрытия внутренних данных является использование непрозрачного типа данных. Основная идея заключается в том, что вы собираете личные данные членов в структуре, например, struct private
. Пользователь получает только указатель на структуру, но не получает информацию о содержимом структуры. Вам нужно будет предоставить все функции, необходимые для работы со скрытыми / личными данными.
Это может выглядеть примерно так:
ns_event.h (для пользователей)
enum ns_event_type{
deleted,
moved
};
struct ns_private; // Opaque data type. The user knows that this type exists
// but have no idea what it contains.
struct ns_event_meta{
enum ns_event_type type;
union {
const char *deleted_path;
struct {
const char *moved_from;
const char *moved_to;
} moved;
} event_data;
struct ns_private *buffer; // The user only gets a pointer to the
// "private" data but can't access the
// members as the user doesn't know
// what's inside
};
// Public functions
int ns_init_buffer(struct ns_event_meta *buffer, size_t size);
int ns_resize_buffer(struct ns_event_meta *buffer, size_t size);
size_t ns_get_buffer_size(struct ns_event_meta *buffer);
void ns_free_buffer(struct ns_event_meta *buffer);
...
...
ns_event.c (ваш код)
struct ns_private {
size_t internal_buffer_size;
void *internal_buffer;
}
int ns_init_buffer(struct ns_event_meta *buffer, size_t size)
{
assert(buffer != NULL);
buffer->internal_buffer = malloc(size);
if (buffer->internal_buffer == NULL)
{
buffer->internal_buffer_size = 0;
return 1;
}
buffer->internal_buffer_size = size;
return 0;
}
...
...
Вы также можете использовать дескриптор вместо указателя на непрозрачный тип данных. Как
struct ns_event_meta{
enum ns_event_type type;
union {
const char *deleted_path;
struct {
const char *moved_from;
const char *moved_to;
} moved;
} event_data;
int handle; // A handle to hide the location of "private" data
// Translation will be needed in the c-file
};
handle
будет просто целым числом, выбранным вашим кодом при вызове ns_init_buffer
. Внутри вашего кода у вас будет таблица, которая переводит между номерами дескрипторов и указателями на личные данные. Таким образом, пользователь никогда не узнает, где хранятся личные данные, и даже не узнает имя структуры, содержащей личные данные.
примечание: хранение ручки внутри структуры - дело вкуса. Вы можете удалить его из структуры и позволить init-функции возвращать дескриптор. Затем пользователь должен сохранить дескриптор в другой переменной и передать его в качестве дополнительного аргумента функции.