Newer
Older
libj / j / lang / src / dl.cpp
#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