如果你想遵循LoadLibrary/GetProcAddress/FreeLibrary的方法,考虑下面的“代码路径”(注意如果你有DLL公共头文件和对应的.lib文件,只需@987654326 @公共 DLL 头文件,并与 .lib 文件链接,并且只需使用原型在 DLL 头文件中定义的函数,就像使用从 C++ 代码调用的普通 C 函数一样。
为 指向从 DLL 导出的函数的指针定义一个 typedef。
请注意,指定了调用约定(通常,带有纯C 接口的Win32 DLL 使用__stdcall calling convention):
//
// Prototype of the DLL function, with *calling convention* specified
// (usually it's __stdcall for DLL with pure-C interface).
//
typedef BOOL (__stdcall *CreateNewScannerPtr)(NewScanner *);
然后您尝试加载 DLL 使用 LoadLibrary:
//
// 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 风格的强制转换。
而且,由于函数指针的type是在reinterpret_cast中指定的,在语句开头重复也没用,所以可以使用新的C++11的关键字auto。
您可以使用返回的函数指针来调用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 pattern,并定义一个带有析构函数的类,该析构函数自动释放 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!!!
注意代码是如何简化的,这要归功于RaiiDll destrutor(以及FreeLibrary)的自动调用,在错误路径的情况下也是如此。