/* =============================================================================
 *  scpp_dl.cpp
 *  Copyright (c)  2003 - 2011  Nomura Kei
 *  LICENSE :
 *  LGPL (GNU Lesser General General Public License - Version 3,29 June 2007)
 *  http://www.gnu.org/copyleft/lesser.html
 * =============================================================================
 *
 *  ライブラリの動的ロードを行うモジュール
 *
 */
#include <scpp_os.hpp>

#if (!SCPP_IS_WINDOWS)
#include <dlfcn.h>
#endif

#include <scpp_dl.hpp>


namespace scpp
{


/**
 * ローダを構築します.
 */
DynamicLinkingLoader::DynamicLinkingLoader() : handle(0)
{
}


/**
 * ロードしたライブラリのハンドルを開放します.
 */
DynamicLinkingLoader::~DynamicLinkingLoader()
{
	if (this->handle)
	{
#if (SCPP_IS_WINDOWS)
		::FreeLibrary(this->handle);
#else
		::dlclose(this->handle);
#endif
		this->handle = 0;
	}
}


/**
 * 指定された fileName のライブラリをロードします.
 * 既にロードされている場合, false を返します.
 *
 * @param fileName ファイル名
 * @return true/false (ロード成功/失敗)
 */
bool DynamicLinkingLoader::open(const std::string& fileName)
{
	if (this->handle)
	{	// 既にロード済み
		return false;
	}

#if (SCPP_IS_WINDOWS)
	this->handle = ::LoadLibraryEx(fileName.c_str(), 0, LOAD_WITH_ALTERED_SEARCH_PATH);
#else
	this->handle = ::dlopen(fileName.c_str(), RTLD_LAZY);
#endif

	return (this->handle != 0);

}


/**
 * 指定されたシンボルがロードされたメモリのアドレスを返します.
 *
 * @code
 * @endcode
 *
 * @param symbol シンボル
 * @return シンボルのアドレス
 */
dl_func_t DynamicLinkingLoader::sym(const std::string& symbol)
{
	if (!this->handle)
	{	// ライブラリがまだロードされていない
		return 0;
	}

	dl_func_t func;
#if (SCPP_IS_WINDOWS)
	func = ::GetProcAddress(this->handle, symbol.c_str());
#else
	func = ::dlsym(this->handle, symbol.c_str());
#endif
	return func;
}



}	// namespace scpp

