如果你想遵循LoadLibrary
//的方法GetProcAddress
,FreeLibrary
考虑下面的“代码路径”(注意,如果你有 DLL 公共头文件和对应的 .lib 文件,只有#include
公共 DLL 头文件,并与 .lib 文件链接,并且只需使用其原型在 DLL 头文件中定义的函数,就像使用从 C++ 代码调用的普通 C 函数一样)。
定义一个typedef
指向从 DLL 导出的函数的指针。
请注意,指定了调用约定(通常,具有纯 C 接口的 Win32 DLL 使用__stdcall
调用约定):
//
// Prototype of the DLL function, with *calling convention* specified
// (usually it's __stdcall for DLL with pure-C interface).
//
typedef BOOL (__stdcall *CreateNewScannerPtr)(NewScanner *);
然后您尝试使用以下方法加载 DLLLoadLibrary
:
//
// Try loading the DLL.
//
HMODULE hDll = LoadLibrary(L"WinScanner.dll"); // <--- Note the use of L"..." for Unicode
if (! hDll)
{
.... error
}
请注意,DLL 的文件名是一个Unicode 字符串(注意L"..."
装饰)。通常,您应该在现代 C++/Win32 代码中使用 Unicode。
然后您可以尝试使用以下方法获取函数指针GetProcAddress
:
//
// Try getting the pointer to CreateNewScanner DLL function.
//
auto pCreateNewScanner = reinterpret_cast<CreateNewScannerPtr>
(
GetProcAddress
(
hDll, // DLL handle
"CreateNewScanner" // Function name
)
);
if (! pCreateNewScanner)
{
.... error
// Release the DLL
FreeLibrary(hDll);
// Avoid dangling references
hDll = nullptr;
}
请注意,由于您使用的是 C++,因此最好使用C++ 风格的转换(如reinterpret_cast<>
本例所示),而不是旧的 C 风格的转换。
而且,由于函数指针的类型reinterpret_cast
是在 中指定的,在语句开头重复也没用,所以auto
可以使用new C++11的关键字。
您可以使用返回的函数指针来调用 DLL 函数:
BOOL retCode = pCreateNewScanner( .... );
// Note: some other common prefix used in this case is "pfn"
// as "pointer to function" (e.g. pfnCreateNewScanner).
使用完 DLL 后,您可以释放它,调用FreeLibrary
:
//
// Release the DLL
//
FreeLibrary(hDll);
hDll = nullptr;
此外,请注意,您可以使用C++ RAII模式,并使用自动释放 DLL的析构函数定义一个类(这简化了管理库加载/释放部分的代码)。
例如
class RaiiDll
{
public:
// Load the DLL.
explicit RaiiDll(const std::wstring& filename) // may also provide an overload
// with (const wchar_t*)
{
m_hDll = ::LoadLibrary(filename.c_str());
if (! m_hDll)
{
// Error
throw std::runtime_error("Can't load the DLL - LoadLibrary() failed.");
// .... or use some other exception...
}
}
// Safely and automatically release the DLL.
~RaiiDll()
{
if (m_hDll)
{
::FreeLibrary(m_hDll);
m_hDll = nullptr;
}
}
// Get DLL module handle.
HMODULE Get() const
{
return m_hDll;
}
private:
HMODULE m_hDll; // DLL instance handle
//
// Ban copy (if compiler supports new C++11 =delete, use it)
//
private:
RaiiDll( RaiiDll & );
RaiiDll & operator=( RaiiDll & );
};
然后,在某些代码块中,您可以拥有:
{
// Load the library (throws on error).
RaiiDll scannerDll(L"WinScanner.dll");
// Get DLL function pointer
auto pCreateNewScanner = reinterpret_cast<CreateNewScannerPtr>(
GetProcAddress(scannerDll.Get(), "CreateNewScanner"));
if (! pCreateNewScanner)
{
.... error.
}
.... use the function
} // <--- DLL automatically released thanks to RaiiDll destructor!!!
请注意,由于自动调用destrutor(等等),代码是如何被简化的,在错误路径的情况下也是如此。RaiiDll
FreeLibrary