Заполнить указатели глобальных функций в общей библиотеке (Solaris, Sun Studio)

StackOverflow https://stackoverflow.com/questions/7818050

Вопрос

Я создаю небольшую общую библиотеку C ++ вокруг библиотеки Fortran 95. Поскольку символы Fortran содержат . В имени символа я должен использовать dlsym Чтобы загрузить функцию Fortran в указатель функции C ++.

В настоящее время у меня есть куча глобальных указателей функций в файлах заголовков:

// test.h
extern void (*f)(int* arg);

и я заполняю их в соответствующем файле C ++:

// test.cc
void (*f))(int* = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");

Вопросы:

  1. Если я сделаю это так, Когда эти указатели заполнены?
  2. Могу ли я предположить, что они будут загружены в мой исполняемый файл, который загружает эту библиотеку?
  3. Особенно, Могу ли я использовать эти функции в статически созданных объектах В моих исполняемых или других библиотеках? Или это страдает от Статическое фиаско порядка статического итализации?
  4. Если вышеупомянутый способ не верен, Какой самый элегантный способ заполнить эти указатели Такой, что их можно использовать в статических объектах в исполняемых файлах и других библиотеках?

Я использую компилятор Sun Studio на Solaris, если это имеет значение, но я также был бы заинтересован в решении GCC на Linux.

Это было полезно?

Решение

Где строка

f = reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_"));

происходит в test.cc? Указатель будет инициализирован при выполнении строки (что, конечно, зависит от того, когда функция, которая содержит ее, называется). Или вы хотели написать

void (*f)(int* ) = reinterpret_cast<void(*)(int*>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_");

? В этом случае указатель будет инициализирован во время статической инициализации. Это означает, что у вас все еще есть проблемы с инициализацией, если вы пытаетесь использовать указатели в конструкторе статического объекта.

Классическим решением для этого было бы использовать какой -то синглтон:

struct LibraryPointers
{
    void (*f)(int* );
    //  ...
    static LibraryPointers const& instance()
private:
    LibraryPointers();
};

LibraryPointers const&
LibraryPointers::instance()
{
    static LibraryPointers theOneAndOnly;
    return theOneAndOnly;
}

LibraryPointers::LibraryPointers()
    : f( reinterpret_cast<void(*)(int*)>(dlsym(RTLD_DEFAULT, "real_f.symbol_name_")) )
    , //  initialization of other pointers...
{
}

Затем оберните библиотеку в класс C ++, который использует эту структуру, чтобы получить адреса указателей.

И одно последнее замечание: reinterpret_cast Вы пытаетесь сделать, не законно, по крайней мере, формально. (Я думаю, что и Sun CC, и G ++ примут это, однако.) Согласно POSIX, правильный способ получить указатель для функционирования от dlsym было бы:

void (*f)(int* );
*reinterpret_cast<void**>(&f) = dlsym(...);

Однако это не поддается инициализации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top