Заполнить глобальные указатели функций в общей библиотеке (Solaris, Sun Studio) - PullRequest
0 голосов
/ 19 октября 2011

Я создаю небольшую общую библиотеку оболочки 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.

1 Ответ

1 голос
/ 19 октября 2011

Где строка

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(...);

Это не даетсам по себе инициализации, однако.

...