Storing function pointer in std::function
I'm trying to write a C++0x wrapper around dlopen()/dlsym() to dynamically load functions from shared objects:
class DynamicLoader
{
public:
DynamicLoader(std::string co开发者_开发问答nst& filename);
template<class Signature>
std::function<Signature> load(std::string const& functionName);
private:
void *itsLibraryHandle;
};
DynamicLoader::DynamicLoader(std::string const& filename)
{
itsLibraryHandle = dlopen(filename.c_str(), RTLD_LAZY);
if(!itsLibraryHandle)
{ /* Throw Some Error */ }
}
template<class Signature>
std::function<Signature> DynamicLoader::load(std::string const& functionName)
{
return <insert magic here> dlsym(itsHandle, functionName.c_str());
}
Is there a way to convert the void* function pointer returned by dlsym into a std::function?
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;
}
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());
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;
}
精彩评论