Newer
Older
c-interpreter / modules / libkcpp / src / kcpp_dl.cpp
Nomura Kei on 9 Aug 2023 2 KB UPDATE
////////////////////////////////////////////////////////////////////////////////
//
// ライブラリの動的ロードを行うモジュール
//

#include <kcpp_dl.hpp>

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


namespace kcpp
{

	////////////////////////////////////////////////////////////////////////////
	//
	// DynamicLoadException
	//

    /**
     * 最後に発生したエラーメッセージを持つ Exception を構築します。
     * エラーメッセージを取得できない場合、空文字がメッセージに設定されます。
     */
    DynamicLoadException::DynamicLoadException() noexcept : Exception()
    {
        // NOP
    }


    /**
     * コピーコンストラクタ。
     *
     * @param t コピー元
     */
    DynamicLoadException::DynamicLoadException(const DynamicLoadException& t) noexcept : Exception(t)
    {
        // NOP
    }


    /**
     * 指定されたメッセージを持つ Exception を構築します。
     *
     * @param msg メッセージ
     */
    DynamicLoadException::DynamicLoadException(const std::string& msg) noexcept : Exception(msg)
    {
        // NOP
    }


    /**
     * デストラクタ。
     */
    DynamicLoadException::~DynamicLoadException() noexcept
    {
        // NOP
    }



	////////////////////////////////////////////////////////////////////////////
	//
	// DynamicLoader
	//

	/**
	 * 指定された動的ライブラリをロードします。
	 * ロードに失敗した場合、DynamicLoadException を throw します。
	 *
	 * @param name ロードする動的ライブラリ
	 */
	DynamicLoader::DynamicLoader(const std::string& name) : handle(nullptr)
	{
#if (KCPP_IS_WINDOWS)
		handle = ::LoadLibraryEx(name.c_str(), 0, LOAD_WITH_ALTERED_SEARCH_PATH);
#else
		handle = ::dlopen(name.c_str(), RTLD_LAZY);
#endif
		if (handle == nullptr)
		{
			throw DynamicLoadException("can't load file");
		}
	}


	/**
	 * 指定された動的ライブラリをアンロードします。
	 */
	DynamicLoader::~DynamicLoader()
	{
#if (KCPP_IS_WINDOWS)
		::FreeLibrary(handle);
#else
		::dlclose(handle);
#endif
	}


	/**
	 * 指定されたシンボルがロードされたアドレスを返します。
	 * 該当シンボルが見つからない場合、DynamicLoadException を throw します。
	 *
	 * @param name シンボル名
	 */
	dl_func_t DynamicLoader::sym(const std::string& name)
	{
		dl_func_t func;
#if (KCPP_IS_WINDOWS)
		func = ::GetProcAddress(handle, name.c_str());
		if (func == nullptr)
		{
			throw DynamicLoadException("no such symbol");
		}
#else
		(void) dlerror();
		func = ::dlsym(handle, name.c_str());
		char* errmsg = dlerror();
		if (errmsg != nullptr)
		{
			throw DynamicLoadException(errmsg);
		}
#endif
		return func;
	}

}