Скройте определение структуры в статической библиотеке

Я должен предоставить статическую библиотеку C клиенту и должен смочь сделать определение структуры недоступным. К тому же я должен смочь выполнить код перед основным при инициализации библиотеки с помощью глобальной переменной.

Вот мой код:

private.h


#ifndef PRIVATE_H
#define PRIVATE_H

typedef struct TEST test;

#endif


private.c (this should end up in a static library)

#include "private.h"
#include <stdio.h>

struct TEST
{
 TEST()
 {
  printf("Execute before main and have to be unavailable to the user.\n");
 }

 int a; // Can be modified by the user
 int b; // Can be modified by the user
 int c; // Can be modified by the user

} TEST;


main.c

test t;

int main( void )
{
 t.a = 0;
 t.b = 0;
 t.c = 0;

 return 0;
}

Очевидно, этот код не работает..., но показывает то, что я должен сделать... Кто-либо знает, как сделать эту работу? Я гуглю вполне немного, но не могу найти ответ, любая справка значительно ценилась бы.

TIA!

6
задан BobMcLaury 24 May 2010 в 07:10
поделиться

3 ответа

Если вы хотите, чтобы клиентский код мог использовать "t.a = ...", вы не можете скрыть определение структуры. То, что вы хотите, называется непрозрачным типом, который будет выглядеть примерно так:

public.h:
struct foo;
set_a( struct foo *, int );
struct foo * new_foo(void);

main.c:
#include <public.h>
int main( void )
{ 
    struct foo *k;
    k = new_foo();
    set_a( k, 5 );
}

Определение структуры доступно только библиотеке. Если вы не сделаете исходный код библиотеки доступным, можно полностью скрыть его от пользователей библиотеки.

3
ответ дан 9 December 2019 в 20:40
поделиться

Если вы используете gcc, вы можете использовать атрибут конструктора,

void runs_before_main(void) __attribute__((constructor))
{
    ...
}

Из документации gcc

Атрибут конструктора вызывает функция, которая будет вызываться автоматически до того, как выполнение войдет в main (). Точно так же атрибут деструктора вызывает функцию автоматически после того, как main () завершено или был вызван exit (). Функции с этими атрибутами полезно для инициализации данных, которые будут неявно использоваться во время выполнение программы.

Вы можете указать необязательное целое число приоритет для контроля порядка, в котором функции конструктора и деструктора запущены. Конструктор с меньшим номер приоритета запускается перед конструктор с большим приоритетом количество; противоположные отношения выполняется для деструкторов. Итак, если у вас есть конструктор, который выделяет ресурс и деструктор, который освобождает один и тот же ресурс, оба функции обычно имеют одинаковые приоритет. Приоритеты для функции конструктора и деструктора такие же, как те, которые указаны для объекты C ++ в области пространства имен

Если вы хотите скрыть структуру от пользователей, объявите структуру в заголовке, но определите ее в файле c, передавая указатели. Например, к

// foo.h
typedef struct private_foo foo;
foo * create_foo(void);
void free_foo(foo * f);

// foo.c
struct private_foo {
    int i;
}
foo * create_foo(void){
    foo * f = malloc(sizeof(*foo));
    if (f) f->i = 1;
    return f;
}
...

foo-> i нельзя будет получить доступ за пределами foo.c .

7
ответ дан 9 December 2019 в 20:40
поделиться

В C нет переносимого способа гарантировать, что ваш код будет работать до main () . Я бы просто поддерживал в вашей библиотеке флаг initialized , установленный в false, а затем отказывался делать что-либо до тех пор, пока не будет вызвана ваша функция init .

Как в:

static int initialised = 0;

int init (void) {
    // do something.
    initialised = 1;
    return ERR_OK;
}

int all_other_functions (void) {
    if (!init)
        return ERR_NOT_INITED;

    // do something.
    return ERR_OK;
}
2
ответ дан 9 December 2019 в 20:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: