POCO库 Foundation::SharedLibrary模块分析

Foundation中的SharedLibrary实现跨平台的dll动态加载。     具体使用方法和简介可见:ShareLibrary官方文档SharedLibrary导出函数      SharedLibrary类的简单用法    通过SharedLibrary可以实现函数导出和类导出,函数导出是最简单的,Dll提供方除了函数需要使用extern "C"声明之外,和普通C++编
摘要由CSDN通过智能技术生成
     Foundation中的SharedLibrary实现跨平台的dll动态加载。
     具体使用方法和简介可见:ShareLibrary官方文档

SharedLibrary导出函数


SharedLibrary类的简单用法

    通过SharedLibrary可以实现函数导出和类导出,函数导出是最简单的,Dll提供方除了函数需要使用extern "C"声明之外,和普通C++编写的dll并无区别,在官方文档的例子中,dll使用方代码也很简单:
     
// LibraryLoaderTest.cpp
#include "Poco/SharedLibrary.h"
using Poco::SharedLibrary;
typedef void (*HelloFunc)(); // function pointer type
int main(int argc, char** argv)
{
        std::string path("TestLibrary");
        path.append(SharedLibrary::suffix()); // adds ".dll" or ".so"
        SharedLibrary library(path); // will also load the library
        HelloFunc func = (HelloFunc) library.getSymbol("hello");
        func();
        library.unload();
        return 0;
}
    其中,SharedLibray::suffix()根据不同的平台和编译模式为dll选择不同的后缀,比如Windows Release版本,则直接添加".dll"后缀,而Windows Debug版本则添加"d.dll"后缀。ShareLibrary在构造时自动加载该动态链接库(在Windows下调用LoadLibrary),然后通过getSymbol(Windows下的GetProcAddress)获取函数地址,这也是之前说要在dll中在函数前用extern "C"声明的原因。

SharedLibrary类的跨平台实现

    SharedLibrary是如何实现跨平台的呢?在Foundation/Inlcude/poco/SharedLibrary.h中,可以看到SharedLibrary从一个叫SharedLibraryImpl的类私有继承,而在SharedLibrary中,几乎所有函数都调用对应的Impl函数:
源代码文件位置:Foundation/src/SharedLibrary.cpp
SharedLibrary::SharedLibrary()
{
}


SharedLibrary::SharedLibrary(const std::string& path)
{
	loadImpl(path, 0);
}


SharedLibrary::SharedLibrary(const std::string& path, int flags)
{
	loadImpl(path, flags);
}


SharedLibrary::~SharedLibrary()
{
}


void SharedLibrary::load(const std::string& path)
{
	loadImpl(path, 0);
}


void SharedLibrary::load(const std::string& path, int flags)
{
	loadImpl(path, flags);
}


void SharedLibrary::unload()
{
	unloadImpl();
}


bool SharedLibrary::isLoaded() const
{
	return isLoadedImpl();
}


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 getPathImpl();
}


std::string SharedLibrary::suffix()
{
	return suffixImpl();
}

而这些函数,恰好在其父类SharedLibraryImpl中实现,而在SharedLibrary.h中,还有这一段:
#if defined(hpux) || defined(_hpux)
#include "SharedLibrary_HPUX.cpp"
#elif defined(POCO_VXWORKS)
#include "SharedLibrary_VX.cpp"
#elif defined(POCO_OS_FAMILY_UNIX)
#include "SharedLibrary_UNIX.cpp"
#elif defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_WIN32_UTF8)
#include "SharedLibrary_WIN32U.cpp"
#elif defined(POCO_OS_FAMILY_WINDOWS)
#include "SharedLibrary_WIN32.cpp"
#elif defined(POCO_OS_FAMILY_VMS)
#include "SharedLibrary_VMS.cpp"
#endif
     通过判断其平台,包含对应的ShareLibrary_*头文件,而在这些文件中,提供了各自的SharedLibraryImpl实现,也就是说,在子类SharedLibrary中调用的load,findSymbol,unload等函数,都最终调用其父类的函数。SharedLibrary_*实现了各个平台下的动态加载功能,而SharedLibrary则通过继承于它统一了这种接口,通过load,getSymbol等函数提供给使用方。
     打开Foundation/src/SharedLibrary_Win32.cpp文件,可以找到SharedLibrary在Windows下的实现,发现下面几个关键函数:
void SharedLibraryImpl::loadImpl(const std::string& path, int /*flags*/)
{
	FastMutex::ScopedLock lock(_mutex);

	if (_handle) throw LibraryAlreadyLoadedException(_path);
	DWORD flags(0);
	Path p(path);
	if (p.isAbsolute()) flags |= LOAD_WITH_ALTERED_SEARCH_PATH;
	_handle = LoadLibraryExA(path.c_str(), 0, flags);
	if (!_handle) throw LibraryLoadException(path);
	_path = path;
}
void* SharedLibraryImpl::findSymbolImpl(const std::string& name)
{
	FastMutex::ScopedLock lock(_mutex);

	if (_handle)
	{
		return (void*) GetProcAddress((HMODULE) _handle, name.c_str());
	}
	else return 0;
}
std::string SharedLibraryImpl::suffixImpl()
{
#if defined(_DEBUG)
	return "d.dll";
#else
	return ".dll";
#endif
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值