标签:des android c class blog code
基于模板元编程技术的跨平台C++动态链接加载库。通过模板技术,使用者仅需通过简单的宏,即可使编译器在编译期自动生成加载动态链接库导出符号的代码,无任何额外的运行时开销。
ASL_LIBRARY_BEGIN(TestLib)
ASL_SYMBOL(Proc_test1, test1, false)
ASL_SYMBOL(Proc_test2, test2, true)
ASL_LIBRARY_END()
TestLib theLib;
try { theLib.Load("./1.so"); }
catch (ASL::LibraryNotFoundException& e)
{
cout << e.what() << endl; // 输出./1.so
}
catch (ASL::SymbolNotFoundException& e)
{
cout << e.what() << endl; // 输出 加载失败的符号名称
}
theLib.test1(1); // assert(theLib.test1 != NULL)
theLib.test2("aa");
theLib.Unload();假定有个一个名为1.so的动态链接库,并且该模块导出test1和test2两个接口。test1的接口类型为Proc_test1, test2的接口类型为Proc_test2。
ASL_SYMBOL宏的第三个参数表示,如果该符号加载失败(模块并没有导出该接口),是否抛出SymbolNotFoundException。 为false时,抛出异常,终止链接库加载流程,并且e.what()为加载失败的符号名称。为true时,忽略错误,仍然继续加载其他符号,客户端可以根据对应的接口是否为NULL来判断该符号是否加载成功。
/********************************************************************
created: 2014/05/31
file base: AutoSharedLibrary
file ext: h
author: qiuhan (hanzz2007@hotmail.com)
purpose: Cross platform classes and macros to make dynamic link module
easy to use by using c++ template meta programming technic.
No need to make any changes to existing module code.
Support both windows(*.dll) and linux(*.so) platforms (wchar_t & char).
SPECIAL THANKS TO TRL (Template Relection Library)
usage:
Following codes are all in client side:
ASL_LIBRARY_BEGIN(ClassName)
ASL_SYMBOL(Proc_func1, func1, true)
ASL_SYMBOL(Proc_func2, func2, false)
ASL_LIBRARY_END()
ClassName theLib;
try {
theLib.Load("./1.so");
}
catch (ASL::LibraryNotFoundException& e) {
}
catch (ASL::SymbolNotFoundException& e) {
}
theLib.func1(1);
theLib.func2("aa");
theLib.Unload();
*********************************************************************/
#ifndef ASL_INCLUDE_H
#define ASL_INCLUDE_H
#ifdef WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
#include <cstdlib>
#include <exception>
#include <string>
namespace ASL {
namespace Private {
template <class Head_, class Tail_>
struct TypeList
{
typedef Head_ Head;
typedef Tail_ Tail;
};
class NullType {};
template <int i_>
struct Int2Type
{
enum { value = i_ };
};
template <int condition_, class T0_, class T1_>
struct Select
{
typedef T0_ Result;
};
template <class T0_, class T1_>
struct Select<false, T0_, T1_>
{
typedef T1_ Result;
};
template <int condition_, int v0_, int v1_>
struct SelectInt
{
enum { value = v0_ };
};
template <int v0_, int v1_>
struct SelectInt<false, v0_, v1_>
{
enum { value = v1_ };
};
template <class Type_, int Ignore_>
struct MemberInfo
{
typedef Type_ Type;
enum {
ignore = Ignore_
};
};
template <class TList_, int startLine_, int endLine_, class ConcreteClass_>
struct CreateMemberIndicesImpl
{
typedef typename ConcreteClass_::template IsMemberPresent<endLine_> IsMemberPresent;
enum { isMemberPresent = IsMemberPresent::value };
typedef typename Select< isMemberPresent
, TypeList<MemberInfo<Int2Type<IsMemberPresent::index>, IsMemberPresent::ignoreError >, TList_>
, TList_ >::Result NewTList;
typedef CreateMemberIndicesImpl<NewTList, startLine_, endLine_ - 1, ConcreteClass_> MemberIndicesImpl;
typedef typename MemberIndicesImpl::Indices Indices;
};
template <class TList_, int startLine_, class ConcreteClass_>
struct CreateMemberIndicesImpl<TList_, startLine_, startLine_, ConcreteClass_>
{
typedef TList_ Indices;
};
template <int startLine_, int endLine_, class ConcreteClass_>
struct CreateMemberIndices
{
typedef CreateMemberIndicesImpl< NullType, startLine_
, endLine_ - 1, ConcreteClass_ > MemberIndicesImpl;
typedef typename MemberIndicesImpl::Indices Indices;
};
template <class ConcreteClass_, int startLine_, int currentLine_>
struct GetMemberIndex
{
typedef typename ConcreteClass_::template IsMemberPresent<currentLine_> IsMemberPresent;
enum {
index = SelectInt< IsMemberPresent::value
, IsMemberPresent::index
, GetMemberIndex<ConcreteClass_, startLine_, currentLine_ - 1>::index >::value + 1
};
};
template <class ConcreteClass_, int startLine_>
struct GetMemberIndex<ConcreteClass_, startLine_, startLine_>
{
enum { index = -1 };
};
}
class DefaultLibraryLoader
{
public:
typedef void* LibHandle;
DefaultLibraryLoader()
{
lib_handle = NULL;
}
template<class Char_>
bool Load(const Char_* name)
{
#if defined(WIN32)
lib_handle = ::LoadLibrary(name);
#else
lib_handle = dlopen(name, RTLD_LAZY);
#endif
return lib_handle != NULL;
}
void Unload()
{
if (!lib_handle) {
return;
}
#if defined(WIN32)
::FreeLibrary((HMODULE)lib_handle);
#elif !defined(_ANDROID)
dlclose(lib_handle);
#endif
lib_handle = NULL;
}
template<class Char_>
void* LoadSymbol(const Char_* fun_name)
{
#if defined(WIN32)
return (void *)::GetProcAddress((HMODULE)lib_handle, fun_name);
#elif !defined(_ANDROID)
return dlsym(lib_handle, fun_name);
#endif
}
private:
LibHandle lib_handle;
};
class LibraryNotFoundException : public std::exception
{
public:
LibraryNotFoundException(const char* err)
{
_err = err;
}
LibraryNotFoundException(const wchar_t* err)
{
static const size_t CONVERT_LEN = 256;
char mbsBuff[CONVERT_LEN + 1] = { 0 };
std::wcstombs(mbsBuff, err, CONVERT_LEN);
_err = mbsBuff;
}
~LibraryNotFoundException() throw() {}
virtual const char* what() const throw() {
return _err.c_str();
}
private:
std::string _err;
};
class SymbolNotFoundException : public std::exception
{
public:
SymbolNotFoundException(const char* err)
{
_err = err;
}
SymbolNotFoundException(const wchar_t* err)
{
static const size_t CONVERT_LEN = 256;
char mbsBuff[CONVERT_LEN + 1] = { 0 };
std::wcstombs(mbsBuff, err, CONVERT_LEN);
_err = mbsBuff;
}
~SymbolNotFoundException() throw() { }
virtual const char* what() const throw() {
return _err.c_str();
}
std::string _err;
};
struct DefaultErrorHandler
{
template<class Char_>
static void OnLoadLibrary(const Char_* libName)
{
throw LibraryNotFoundException(libName);
}
template<class Char_>
static void OnLoadSymbol(const Char_* symbolName, const bool ignore)
{
if (!ignore) {
throw SymbolNotFoundException(symbolName);
}
}
};
template < class ConcreteClass_,
class Loader_ = DefaultLibraryLoader,
class ErrorHandler_ = DefaultErrorHandler >
class AutoSharedLibrary
{
public:
AutoSharedLibrary()
{
}
~AutoSharedLibrary()
{
Unload();
}
template<class Char_>
void Load(ConcreteClass_& object, const Char_* p)
{
if (!_loader.Load(p)) {
ErrorHandler_::OnLoadLibrary(p);
}
typedef typename ConcreteClass_::MemberIndices Indices;
LoadSymbols(object, Indices());
}
void Unload()
{
_loader.Unload();
}
private:
template <class Indices_>
void LoadSymbols(ConcreteClass_& object, Indices_ indices)
{
typedef typename Indices_::Head SymInfo;
typedef typename SymInfo::Type Index;
bool ret = LoadSymbol(object.getLoadName(Index()),
object.*ConcreteClass_::getMemberPtr(Index()));
if (!ret) {
ErrorHandler_::OnLoadSymbol(object.getLoadName(Index()), (bool)SymInfo::ignore);
}
LoadSymbols(object, typename Indices_::Tail());
}
void LoadSymbols(ConcreteClass_& object, Private::NullType indices)
{
}
template <class FuncType_, class Char_>
bool LoadSymbol(const Char_* funcName, FuncType_& func)
{
func = (FuncType_)_loader.LoadSymbol(funcName);
return func != NULL;
}
Loader_ _loader;
};
}
#define ASL_LIBRARY_BEGIN(ConcreteClass_) ASL_LIBRARY_BEGIN_2(ConcreteClass_, ASL::DefaultLibraryLoader, ASL::DefaultErrorHandler)
#define ASL_LIBRARY_BEGIN_2(ConcreteClass_, LibraryLoader_, ErrorHandler_) class ConcreteClass_ { private: typedef ConcreteClass_ ConcreteClass; enum { startLine = __LINE__ }; ASL::AutoSharedLibrary<ConcreteClass_, LibraryLoader_, ErrorHandler_> _libLoader; public: ConcreteClass_() { } ~ConcreteClass_() { Unload(); } template<class Char_> void Load(const Char_* p) { _libLoader.Load(*this, p); } void Unload() { _libLoader.Unload(); } template <int lineNb_, class Dummy_ = ASL::Private::NullType> struct IsMemberPresent { enum { value = false }; enum { index = 0 }; enum { ignoreError = false }; };
#define ASL_SYMBOL_2(DataType, name, loadName, ignoreNotFound) public: DataType name; private: typedef DataType ConcreteClass::* MemberPtr##name; public: template <class Dummy_> struct IsMemberPresent<__LINE__, Dummy_> { enum { value = true }; enum { index = ASL::Private::GetMemberIndex< ConcreteClass, startLine, __LINE__ - 1>::index }; enum { ignoreError = ignoreNotFound}; }; static const char* getLoadName( ASL::Private::Int2Type<IsMemberPresent<__LINE__>::index >) { return #loadName; } static MemberPtr##name getMemberPtr( ASL::Private::Int2Type< IsMemberPresent<__LINE__>::index >) { return &ConcreteClass::name; }
#define ASL_SYMBOL(DataType, name, ignoreNotFound) ASL_SYMBOL_2(DataType, name, name, ignoreNotFound)
#define ASL_LIBRARY_END() private: enum { endLine = __LINE__ }; public: typedef ASL::Private::CreateMemberIndices<startLine, endLine, ConcreteClass> ::Indices MemberIndices; };
#endif
AutoSharedLibrary -- 基于模板元编程技术的跨平台C++动态链接加载库,布布扣,bubuko.com
AutoSharedLibrary -- 基于模板元编程技术的跨平台C++动态链接加载库
标签:des android c class blog code
原文地址:http://blog.csdn.net/hanzz2007/article/details/27883883