/**
* @file SharedLibrary.h
*
* Copyright (c) 2011, FOREVEROSS
*
* @brief 共享库的动态加载
*
*
* @version 1.0.0
* @author Yifeng Liu
* @date 2011-05-20
*
*
* record:
*
* 2011-05-20 Create by Yifeng Liu
*
*/
#ifndef _BASE_SHARED_LIBRARY_H_
#define _BASE_SHARED_LIBRARY_H_
#include "Base/ThreadMutex.h"
namespace CPP {
namespace Base {
/// 动态加载卸载动态库
class SharedLibrary
{
public:
/// 构造函数。
///
/// @param 无
/// @return 无
/// @see SharedLibrary(const std::string& path)
/// @note 无
SharedLibrary();
/// 构造函数。
///
/// @param path 动态库路径加名字
/// @return 无
/// @see SharedLibrary()
/// @note 无
SharedLibrary(const std::string& path);
/// 析构函数。
///
/// @param 无
/// @return 无
/// @see 无
/// @note 无
virtual ~SharedLibrary();
/// 加载动态库。
///
/// @param path 动态库的路径
/// @return 无
/// @see 无
/// @note 可以抛出LibraryAlreadyLoadedException或LibraryLoadException
void Load(const std::string& path);
/// 卸载动态库。
///
/// @param 无
/// @return 无
/// @see 无
/// @note 无
void Unload();
/// 判断动态库是否加载过。
///
/// @param 无
/// @return 已经加载返回true,否则返回false
/// @see 无
/// @note 无
bool IsLoaded() const;
/// 判断动态符号是否存在
///
/// @param name 动态符号的名字
/// @return 如果存在返回true,否则返回false
/// @see Exception(const Exception& exc)
/// @note (note描述需要注意的问题)
bool HasSymbol(const std::string& name);
/// 取动态符号的地址
///
/// @param name 动态符号的名字
/// @return 返回动态符号的地址,即为函数地址
/// @see 无
/// @note 可以抛出NotFoundException
void* GetSymbol(const std::string& name);
/// 返回动态的路径和名字。
///
/// @param 无
/// @return 无
/// @see 无
/// @note 无
const std::string& GetPath() const;
/// 返回动态库的后缀。
///
/// @param 无
/// @return 无
/// @see 无
/// @note 不同操作系统上的后缀会有不同
static std::string Suffix();
private:
void LoadImpl(const std::string& path);
void UnloadImpl();
bool IsLoadedImpl() const;
void* FindSymbolImpl(const std::string& name);
private:
std::string _path;
void* _handle;
static ThreadMutex _mutex;
private:
SharedLibrary(const SharedLibrary&);
SharedLibrary& operator = (const SharedLibrary&);
};
} // namespace Base
} // namespace CPP
#endif // _BASE_SHARED_LIBRARY_H_
/**
* @file Thread.cpp
*
* Copyright (c) 2011, FOREVEROSS
*
*/
#include "Base/SharedLibrary.h"
#include "Base/Exception.h"
#include <dlfcn.h>
namespace CPP {
namespace Base {
ThreadMutex SharedLibrary::_mutex;
SharedLibrary::SharedLibrary()
{
_handle = 0;
}
SharedLibrary::SharedLibrary(const std::string& path)
{
LoadImpl(path);
}
SharedLibrary::~SharedLibrary()
{
}
void SharedLibrary::Load(const std::string& path)
{
LoadImpl(path);
}
void SharedLibrary::Unload()
{
UnloadImpl();
}
bool SharedLibrary::IsLoaded() const
{
return _handle != 0;
}
bool SharedLibrary::HasSymbol(const std::string& name)
{
return FindSymbolImpl(name) != 0;
}
void* SharedLibrary::GetSymbol(const std::string& name)
{
void* result = FindSymbolImpl(name);
if (result)
{
return result;
}
else
{
throw NotFoundException(name);
}
}
const std::string& SharedLibrary::GetPath() const
{
return _path;
}
std::string SharedLibrary::Suffix()
{
return ".so";
}
void SharedLibrary::LoadImpl(const std::string& path)
{
ThreadMutex::ThreadLock lock(_mutex);
if (_handle)
{
throw LibraryAlreadyLoadedException(path);
}
_handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
if (!_handle)
{
const char* err = dlerror();
throw LibraryLoadException(err ? std::string(err) : path);
}
_path = path;
}
void SharedLibrary::UnloadImpl()
{
ThreadMutex::ThreadLock lock(_mutex);
if (_handle)
{
dlclose(_handle);
_handle = 0;
}
}
void* SharedLibrary::FindSymbolImpl(const std::string& name)
{
ThreadMutex::ThreadLock lock(_mutex);
void* result = 0;
if (_handle)
{
result = dlsym(_handle, name.c_str());
}
return result;
}
} // namespace Base
} // namespace CPP