在共享库中填充全局函数指针(Solaris, Sun Studio)

Populate global function pointers in shared library (Solaris, Sun Studio)

本文关键字:Solaris Sun Studio 指针 函数 共享 填充 全局      更新时间:2023-10-16

我正在创建一个围绕Fortran 95库的小型c++包装器共享库。由于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. 如果上面的方法不正确,填充这些指针的最优雅的方法是什么? 使它们可以在可执行文件和其他库中的静态对象中使用?

我在Solaris上使用Sun Studio编译器,如果这有区别的话,但我也对Linux上的GCC解决方案感兴趣。

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_");

?在这种情况下,指针将在static期间初始化初始化。这意味着你还有初始化的顺序尝试在静态的构造函数中使用指针会产生问题对象。

经典的解决方案是使用某种类型的单例:
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的说法,得到a的正确方法是从dlsym指向函数的指针应该是:

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