Last active
August 29, 2015 14:01
-
-
Save max630/9a54b947f211b33258bb to your computer and use it in GitHub Desktop.
dynamic c++ calls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <boost/any.hpp> | |
#include <dlfcn.h> | |
namespace impl { | |
inline void* gate(const char* libname, const char* name, const char** err) | |
{ | |
dlerror(); | |
void* lib = dlopen(libname, RTLD_NOW); | |
if (lib == nullptr) { | |
*err = dlerror(); | |
return nullptr; | |
} | |
void* sym = dlsym(lib, name); | |
*err = dlerror(); | |
if (*err != nullptr) return nullptr; | |
return sym; | |
} | |
} | |
template <class Def> | |
class Dynamic { | |
typedef decltype(Def::Default) ResultType; | |
public: | |
static ResultType* Get() | |
{ | |
static ResultType* Result = nullptr; | |
if (Result == nullptr) { | |
Dynamic<Def> worker; | |
if (!worker.Resolve(Def::Libname(), Def::Name())) | |
Def::Error(worker.Error()); | |
Result = worker.Result; | |
} | |
return Result; | |
} | |
bool Resolve(const std::string& libname, const std::string& name) | |
{ | |
const char* err_c = nullptr; | |
boost::any* res1 = static_cast<boost::any*>(impl::gate(libname.c_str(), name.c_str(), &err_c)); | |
if (res1 == nullptr) { | |
error = err_c; | |
Result = Def::Default; | |
return false; | |
} | |
auto res2 = boost::any_cast<ResultType*>(res1); | |
if (res2 == nullptr) { | |
error = std::string("Bad cast: ") + name + " to: " + typeid(ResultType*).name(); | |
Result = Def::Default; | |
return false; | |
} | |
Result = *res2; | |
return true; | |
} | |
std::string Error() const | |
{ | |
return error; | |
} | |
private: | |
ResultType* Result; | |
std::string error; | |
}; | |
#define DEF_DEFAULT(_libname, _name) \ | |
static std::string Libname() { return _libname; } \ | |
static std::string Name() { return _name; } \ | |
static void Error(const std::string& msg) { \ | |
std::cerr << "Error: " << msg << std::endl; \ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "dynamic.h" | |
#include <iostream> | |
struct DefTest { | |
static std::string Default() { return "default"; } | |
static std::string Libname() { return "./dynamic_lib.so"; } | |
static std::string Name() { return "dynamic_lib_test"; } | |
static void Error(const std::string& msg) { | |
std::cerr << "Error: " << msg << std::endl; | |
} | |
}; | |
struct DefTest2 { | |
static std::string Default() { return "default"; } | |
DEF_DEFAULT("./dynamic_lib.so", "dynamic_lib_test2") | |
}; | |
struct DefTest3 { | |
static int Default() { return 42; } | |
DEF_DEFAULT("./dynamic_lib.so", "dynamic_lib_test") | |
}; | |
int main() | |
{ | |
std::string error; | |
std::cout << "Func1: " << Dynamic<DefTest>::Get()() << std::endl; | |
std::cout << "Func2: " << Dynamic<DefTest2>::Get()() << std::endl; | |
std::cout << "Func3: " << Dynamic<DefTest3>::Get()() << std::endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <boost/any.hpp> | |
#include <string> | |
std::string test() | |
{ | |
return "hello"; | |
} | |
extern "C" { | |
boost::any dynamic_lib_test = &test; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: dynamic_lib.so dynamic | |
dynamic_lib.so: dynamic_lib.cc dynamic.h | |
g++ -g -Wall -Werror -std=c++11 -shared -o dynamic_lib.so dynamic_lib.cc | |
dynamic: dynamic_client.cc dynamic.h | |
g++ -g -Wall -Werror -std=c++11 -o dynamic dynamic_client.cc -ldl |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment