Storing function pointer in std::function

前端 未结 3 740
囚心锁ツ
囚心锁ツ 2021-02-07 15:55

I\'m trying to write a C++0x wrapper around dlopen()/dlsym() to dynamically load functions from shared objects:

class DynamicLoader
{
  public:
    DynamicLoade         


        
相关标签:
3条回答
  • 2021-02-07 16:25

    try this:

    static_cast<Signature*>()
    

    seems works in VC10

    complete test:

    #include <functional>
    
    void test()
    {}
    
    template <typename Signature>
    std::function<Signature> cast(void* f)
    {
        return static_cast<Signature*>(f);
    }
    
    int main()
    {
        std::function<void()> f = cast<void()>(&test);
        return 0;
    }
    
    0 讨论(0)
  • 2021-02-07 16:43

    You just need to cast result of dlsym() call to a proper type. Here's a complete working example:

    #include <functional>
    #include <iostream>
    #include <stdexcept>
    #include <string>
    #include <dlfcn.h>
    
    class DynamicLoader
    {
    public:
        DynamicLoader(std::string const& filename) :
            m_handle(dlopen(filename.c_str(), RTLD_LAZY))
        {
            if (!m_handle)
            {
                throw std::logic_error("can't load library named \"" + filename + "\"");
            }
        }
    
        template<class T>
        std::function<T> load(std::string const& functionName) const
        {
            dlerror();
            void* const result = dlsym(m_handle, functionName.c_str());
            if (!result)
            {
                char* const error = dlerror();
                if (error)
                {
                    throw std::logic_error("can't find symbol named \"" + functionName + "\": " + error);
                }
            }
    
            return reinterpret_cast<T*>(result);
        }
    
    private:
        void* const m_handle;
    };
    
    int main()
    {
        DynamicLoader const loader("/lib64/libz.so.1");
        auto const zlibVersion = loader.load<char const* (void)>("zlibVersion");
        std::cout << "zlib version: " << zlibVersion() << std::endl;
        return 0;
    }
    
    0 讨论(0)
  • 2021-02-07 16:49

    Based on what I see here: http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html

    #include <boost/function_types/components.hpp>
    #include <boost/function_types/function_pointer.hpp>
    
    template< typename Signature >
    std::function<Signature> DynamicLoader::load(std::string const& name)
    {
      namespace ft = boost::function_types;
      typedef typename ft::function_pointer< typename ft::components<Signature>::type >::type fp_t;
      fp_t fun_ptr;
    
      *reinterpret_cast<void**>(&fun_ptr) = dlsym(itsHandle, name.c_str());
    
      return fun_ptr;
    }
    

    I've never used dlsym so I don't understand why the cast is being done that way and not simply casting dlsym's return like so:

    fun_ptr = reinterpret_cast<fp_t>(dlsym(itsHandle, name.c_str());
    
    0 讨论(0)
提交回复
热议问题