简体   繁体   English

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

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

I am creating a small C++ wrapper shared library around a Fortran 95 library. 我正在围绕Fortran 95库创建一个小的C ++包装程序共享库。 Since the Fortran symbols contain . 由于Fortran符号包含. in the symbol name, I have to use dlsym to load the Fortran function into a C++ function pointer. 在符号名称中,我必须使用dlsym将Fortran函数加载到C ++函数指针中。

Currently, I have a bunch of global function pointers in header files: 当前,我在头文件中有一堆全局函数指针:

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

and I populate them in the corresponding C++ file: 然后将它们填充到相应的C ++文件中:

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

Questions: 问题:

  1. If I do it this way, when are these pointers populated? 如果我这样做, 这些指针何时填充?
  2. Can I assume them to be loaded in my executable that loads this library? 我可以假定它们已加载到我的可执行文件中,该可执行文件可以加载该库吗?
  3. In particular, can I use these functions in statically created objects in my executable or other libraries? 特别是, 可以在可执行文件或其他库中的静态创建的对象使用这些功能吗? Or does this suffer from the static initalization order fiasco ? 还是这会遭受静态初始化顺序的惨败
  4. If the above way is not correct, what is the most elegant way of populating these pointers such that they can be used in static objects in executables and other libraries? 如果上述方法不正确, 那么填充这些指针以便可以在可执行文件和其他库中的静态对象中使用的最优雅的方法是什么?

I am using the Sun Studio compiler on Solaris, if that makes a difference, but I would also be interested in a solution for GCC on Linux. 我可以在Solaris上使用Sun Studio编译器,如果有区别的话,但是我也对Linux上的GCC解决方案感兴趣。

Where does the line 线在哪里

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

occur in test.cc ? 发生在test.cc吗? The pointer will be initialized when the line is executed (which of course depends on when the function which contains it is called). 指针将在执行该行时初始化(这当然取决于何时调用包含该指针的函数)。 Or did you mean to write 还是你想写

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

? In this case, the pointer will be initialized during static initialization. 在这种情况下,指针将在静态初始化期间初始化。 Which means that you still have order of initialization issues if you try to use the pointers in the constructor of a static object. 这意味着,如果您尝试在静态对象的构造函数中使用指针,则仍然存在初始化问题的顺序。

The classical solution for this would be to use some sort of singleton: 对此的经典解决方案是使用某种单例:

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...
{
}

Then wrap the library in a C++ class which uses this structure to get the addresses of the pointers. 然后将库包装在一个C ++类中,该类使用此结构来获取指针的地址。

And one last remark: the reinterpret_cast you are trying to do isn't legal, at least not formally. 最后一句话:您尝试执行的reinterpret_cast非法,至少在形式上不合法。 (I think that both Sun CC and g++ will accept it, however.) According to Posix, the correct way to get a pointer to function from dlsym would be: (但是,我认为Sun CC和g ++都会接受它。)根据Posix的说法,从dlsym获取指向函数的指针的正确方法是:

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

This doesn't lend itself to initializations, however. 但是,这并不适合进行初始化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM