Скрыть определение структуры в статической библиотеке - PullRequest
6 голосов
/ 24 мая 2010

Мне нужно предоставить клиенту статическую библиотеку 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;
}

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

ТИА!

Ответы [ 3 ]

7 голосов
/ 24 мая 2010

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

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

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

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

Вы можете указать необязательное целое число приоритет контролировать порядок, в котором функции конструктора и деструктора запускаются. Конструктор с меньшим номер приоритета запускается перед конструктор с большим приоритетом число; противоположные отношения держит для деструкторов. Итак, если у вас есть конструктор, который выделяет ресурс и деструктор, который освобождает один и тот же ресурс, оба функции обычно имеют одинаковые приоритет. Приоритеты для функции конструктора и деструктора те же, что указаны для Область имен пространства имен 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.

3 голосов
/ 24 мая 2010

Если вы хотите, чтобы клиентский код мог использовать «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 );
}

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

2 голосов
/ 24 мая 2010

В C нет переносимого способа гарантировать, что ваш код будет работать до main().Я хотел бы просто сохранить флаг initialised в вашей библиотеке, установить значение 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;
}
...