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

发布于 2024-12-10 10:59:41 字数 738 浏览 3 评论 0原文

我正在围绕 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 解决方案感兴趣。

I am creating a small C++ wrapper shared library around a Fortran 95 library. Since the Fortran symbols contain . in the symbol name, I have to use dlsym to load the Fortran function into a C++ function pointer.

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:

// 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧伤还要旧人安 2024-12-17 10:59:41

该行

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

但是,这并不适合初始化。

Where does the line

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

occur in 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.

And one last remark: the reinterpret_cast you are trying to do isn't
legal, at least not formally. (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:

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

This doesn't lend itself to initializations, however.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文