#include <j.hpp>
#if (!IS_WINDOWS)
#include <dlfcn.h>
#endif
#include <j/lang/string.hpp>
#include <j/lang/dl.hpp>
namespace j
{
namespace lang
{
/**
* Dl を構築します。
*/
Dl::Dl(const String &fileName) noexcept
{
#if (IS_WINDOWS)
handle = ::LoadLibraryEx(fileName);
#else
handle = ::dlopen(fileName, RTLD_LAZY);
#endif
// TODO : handle == 0 の場合エラー
}
/**
* Dl のコピーコンストラクタ。
*
* @param dl コピー元オブジェクト
*/
Dl::Dl(const Dl &dl) noexcept : Object(dl), handle(dl.handle)
{ /* NOP */
}
/**
* Dl のムーブコンストラクタ。
*
* @param dl ムーブ元オブジェクト
*/
Dl::Dl(Dl &&dl) noexcept : Object(std::move(dl)), handle(std::move(dl.handle))
{ /* NOP */
}
// デストラクタ
Dl::~Dl() noexcept
{
#if (IS_WINDOWS)
::FreeLibrary(handle);
#else
::dlclose(handle);
#endif
}
/**
* コピー代入演算子。
* コピーして代入します。
*
* @param dl コピー元オブジェクト
* @return 本オブジェクトへの参照
*/
Dl &Dl::operator=(const Dl &dl) noexcept
{
if (this != &dl)
{
Object::operator=(dl);
handle = dl.handle;
}
return *this;
}
/**
* ムーブ代入演算子。
*
* @param dl ムーブ元オブジェクト
* @return 本オブジェクトへの参照
*/
Dl &Dl::operator=(Dl &&dl) noexcept
{
if (this != &dl)
{
Object::operator=(std::move(dl));
handle = std::move(dl.handle);
handle = nullptr;
}
return *this;
}
/**
* 本オブジェクトの文字列表現を返します。
*
* @return 本オブジェクトの文字列表現
*/
String Dl::toString() const noexcept
{
return Object::toString();
}
/**
* 指定されたシンボルがロードされたメモリのアドレスを返します。
*
* @code
* typedef USHORT (WINAPI *RtlCaptureStackBackTraceDef) (ULONG framesToSkip, ULOLNG framesToCapture, PVOID *backTrace, PULONG backTraceHash);
* Dl dl("kernel32.dll");
* RtlCaptureStackBackTraceDef RtlCaptureStackBackTrace = reinterpret_cast<RtlCaptureStackBackTraceDef>(dl.sym("RtlCaptureStackBackTrace"));
* void* buffer[64];
* int cnt = RtlCaptureStackBackTrace(0, 64, buffer, 0);
* for (int i = 0; i < cnt; i++)
* {
* std::cout << buffer[i] << std::endl;
* }
* @endcode
*
* @param symbol シンボル名
* @return シンボルのアドレス
*/
dl_func_t Dl::sym(const String &symbol)
{
#if (IS_WINDOWS)
return ::GetProcAddress(handle, symbol);
#else
return ::dlsym(handle, symbol);
#endif
}
} // namespace lang
} // namespace j