代码之家  ›  专栏  ›  技术社区  ›  sud03r

C++中函数指针的铸造

  •  34
  • sud03r  · 技术社区  · 15 年前

    dlsym()返回了一个void指针,我想调用void指针指向的函数。 所以我通过铸造来进行类型转换:

    void *gptr = dlsym(some symbol..) ;
    typedef void (*fptr)();
    fptr my_fptr = static_cast<fptr>(gptr) ;
    

    我也试过了 reinterpret_cast 但运气不好,尽管C演员组的操作员似乎能工作。

    6 回复  |  直到 6 年前
        1
  •  47
  •   HostileFork says dont trust SE    9 年前

    转换A void* 指向函数指针 直接地 在C++ 98/03中不允许(不使用任何类型的编译)。它在C++0x中有条件支持(一个实现可以选择定义行为,如果它确实定义了它,那么它必须执行标准所说的应该做的事情。一 空洞* 如C++ 98/03标准所定义的,是指指向对象而不包含函数指针或成员指针。

    知道您所做的工作严重依赖于实现,这里有一个选项应该在大多数平台上编译和工作(假设32位指针,使用long long for 64位),尽管根据标准,它显然是未定义的行为:

    void *gptr = dlsym(some symbol..) ;
    typedef void (*fptr)();
    fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<long>(gptr)) ;
    

    这里还有另一个应该编译和工作的选项,但是也有与上面相同的警告:

    fptr my_ptr = 0;
    *reinterpret_cast<void**>(&my_ptr) = gptr; 
    

    或者,慢动作…

    // get the address which is an object pointer
    void (*(*object_ptr))() = &my_ptr;  
    
    // convert it to void** which is also an object pointer
    void ** ppv = reinterpret_cast<void**>(object_ptr);
    
    // assign the address in the memory cell named by 'gptr' 
    // to the memory cell that is named by 'my_ptr' which is
    // the same memory cell that is pointed to 
    // by the memory cell that is named by 'ppv'
    *ppv = gptr;  
    

    它实际上利用了函数指针的地址是一个对象指针这一事实。 [void (*(*object_ptr))()] -所以我们可以使用 reinterpret_cast 将其转换为任何其他对象指针:例如 void** . 然后,我们可以沿着地址返回(通过取消对void**的引用)到实际的函数指针,并将gptr的值存储在那里。

    不错——当然不是定义良好的代码——但是它应该像您期望的那样在大多数实现上执行。

        3
  •  1
  •   BrunoLevy    9 年前

    我发现这个(有点难看)解决方案。 具有最高警告级别的GCC不会投诉。 此示例调用dlsym()(返回void*)并在函数指针中返回结果。

    typedef void (*FUNPTR)();
    
    FUNPTR fun_dlsym(void* handle, const char* name) {
        union {
            void* ptr;
            FUNPTR fptr;
        } u;
        u.ptr = dlsym(handle, name);
        return u.fptr;
    }
    
        4
  •  0
  •   Andrew Best    13 年前

    这在Visual Studio中编译,而不使用reinterpret cast:

    void *ptr;
    int (*func)(void) = (int(*)(void))ptr;
    int num = func();
    
        5
  •  0
  •   Yuriy Vasylenko    6 年前

    可以使用以下技术:

    int (*fn)(int);
    *(void **)(&fn) = dlsym(lib1, "function");
    int result = (*fn)(3);
    

    fn = (int (*)(int))dlsym(lib1, "function");
    

    编译:

    g++ -Wall -pedantic -std=c++11
    
        6
  •  -6
  •   Ryan Oberoi    15 年前

    这可能对你有帮助。上面印着“你好”。

    #include <iostream>
    
    void hello()
    {
      std::cout << "Hello" << std::endl;
    }
    
    int main() {
      typedef void (*fptr)();
      fptr gptr = (fptr) (void *) &hello;
      gptr();
    }
    

    或者你可以这样做:

    fptr gptr = reinterpret_cast<fptr>( (void *) &hello);
    

    其中&hello替换为dlsym命令。