DLL使用
(1)隐式链接到 DLL 的可执行文件在生成时链接到导入库(.lib文件)。
(2)采用显式连接(LoadLibrary和GetProcAddress)时,不需要.lib文件。
函数导出方式
(1)源代码中的 __declspec(dllexport) 关键字
(2).def 文件中的 EXPORTS 语句
(3)LINK 命令中的 /EXPORT 规范
所有这三种方法可以用在同一个程序中。LINK 在生成包含导出的程序时还创建导入库,除非生成中使用了 .exp 文件。
导出
CppDynamicLinkLibrary.cpp
#include "CppDynamicLinkLibrary.h"
#include <strsafe.h>
#pragma region DLLMain
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#pragma endregion
#pragma region Global Data
// An exported/imported global data using a DEF file
// Initialize it to be 1
int g_nVal1 = 1;
// An exported/imported global data using __declspec(dllexport/dllimport)
// Initialize it to be 2
SYMBOL_DECLSPEC int g_nVal2 = 2;
#pragma endregion
#pragma region Ordinary Functions
// An exported/imported cdecl(default) function using a DEF file
int /*__cdecl*/ GetStringLength1(PCWSTR pszString)
{
return static_cast<int>(wcslen(pszString));
}
// An exported/imported stdcall function using __declspec(dllexport/dllimport)
SYMBOL_DECLSPEC int __stdcall GetStringLength2(PCWSTR pszString)
{
return static_cast<int>(wcslen(pszString));
}
#pragma endregion
#pragma region Callback Function
// An exported/imported stdcall function using a DEF file
// It requires a callback function as one of the arguments
int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc)
{
// Make the callback to the comparison function
// If a is greater than b, return a;
// If b is greater than or equal to a, return b.
return ((*cmpFunc)(a, b) > 0) ? a : b;
}
#pragma endregion
#pragma region Class
// Constructor of the simple C++ class
CSimpleObject::CSimpleObject(void) : m_fField(0.0f)
{
}
// Destructor of the simple C++ class
CSimpleObject::~CSimpleObject(void)
{
}
float CSimpleObject::get_FloatProperty(void)
{
return this->m_fField;
}
void CSimpleObject::set_FloatProperty(float newVal)
{
this->m_fField = newVal;
}
HRESULT CSimpleObject::ToString(PWSTR pszBuffer, DWORD dwSize)
{
return StringCchPrintf(pszBuffer, dwSize, L"%.2f", this->m_fField);
}
int CSimpleObject::GetStringLength(PCWSTR pszString)
{
return static_cast<int>(wcslen(pszString));
}
#pragma endregion
CppDynamicLinkLibrary.def
LIBRARY CppDynamicLinkLibrary
EXPORTS
GetStringLength1 @1
CompareInts @2
g_nVal1 DATA
导入
CppLoadLibrary.cpp
#pragma region Includes
#include <stdio.h>
#include <windows.h>
#pragma endregion
// Function pointer types for functions exported from the DLL module
typedef int (_cdecl* LPFNGETSTRINGLENGTH1) (PCWSTR);
// CALLBACK, aka __stdcall, can only be used for stdcall methods. If it is
// used for __cdecl methods, this error will be thrown in runtime: The value
// of ESP was not properly saved across a function call. This is usually a
// result of calling a function declared with one calling convention with a
// function pointer declared with a different calling convention.
typedef int (CALLBACK* LPFNGETSTRINGLENGTH2) (PCWSTR);
// Type-definition of the 'PFN_COMPARE' callback function, and the CompareInts
// function that requires the callback as one of the arguments.
typedef int (CALLBACK* PFN_COMPARE) (int, int);
typedef int (CALLBACK* LPFNMAX) (int, int, PFN_COMPARE);
//
// FUNCTION: IsModuleLoaded(PCWSTR)
//
// PURPOSE: Check whether or not the specified module is loaded in the
// current process.
//
// PARAMETERS:
// * pszModuleName - the module name
//
// RETURN VALUE: The function returns TRUE if the specified module is
// loaded in the current process. If the module is not loaded, the function
// returns FALSE.
//
BOOL IsModuleLoaded(PCWSTR pszModuleName)
{
// Get the module in the process according to the module name.
HMODULE hMod = GetModuleHandle(pszModuleName);
return (hMod != NULL);
}
//
// FUNCTION: Max(int, int)
//
// PURPOSE: This is the callback function for the method Max exported from
// CppDynamicLinkLibrary.dll
//
// PARAMETERS:
// * a - the first integer
// * b - the second integer
//
// RETURN VALUE: The function returns a positive number if a > b, returns 0
// if a equals b, and returns a negative number if a < b.
//
int CALLBACK Max(int a, int b)
{
return (a - b);
}
int wmain(int argc, wchar_t *argv[])
{
BOOL fLoaded = FALSE;
HINSTANCE hModule = NULL;
// The name of the module to be dynamically-loaded.
PCWSTR pszModuleName = L"CppDynamicLinkLibrary";
// Check whether or not the module is loaded.
fLoaded = IsModuleLoaded(pszModuleName);
wprintf(L"Module \"%s\" is %sloaded\n", pszModuleName, fLoaded ? L"" : L"not ");
// Dynamically load the library.
wprintf(L"Load the library\n");
hModule = LoadLibrary(pszModuleName);
if (hModule == NULL)
{
wprintf(L"LoadLibrary failed w/err 0x%08lx\n", GetLastError());
goto Cleanup;
}
// Check whether or not the module is loaded.
fLoaded = IsModuleLoaded(pszModuleName);
wprintf(L"Module \"%s\" is %sloaded\n", pszModuleName, fLoaded ? L"" : L"not ");
//
// Access the global data exported from a module.
//
// Dynamically-loaded DLL does not allow you to access the global data
// exported from the DLL.
//
// Call the functions exported from a module.
//
PCWSTR pszString = L"HelloWorld";
int nLength;
// Call int /*__cdecl*/ GetStringLength1(PWSTR pszString);
LPFNGETSTRINGLENGTH1 lpfnGetStringLength1 = (LPFNGETSTRINGLENGTH1)GetProcAddress(hModule, "GetStringLength1");
if (lpfnGetStringLength1 == NULL)
{
wprintf(L"GetStringLength1 cannot be found (Error: 0x%08lx)\n",
GetLastError());
goto Cleanup;
}
nLength = lpfnGetStringLength1(pszString);
wprintf(L"Function: GetStringLength1(\"%s\") => %d\n", pszString, nLength);
// Call int __stdcall GetStringLength2(PWSTR pszString);
LPFNGETSTRINGLENGTH2 lpfnGetStringLength2 = (LPFNGETSTRINGLENGTH2)GetProcAddress(hModule, "_GetStringLength2@4");
if (lpfnGetStringLength2 == NULL)
{
wprintf(L"GetStringLength2 cannot be found (Error: 0x%08lx)\n",
GetLastError());
goto Cleanup;
}
nLength = lpfnGetStringLength2(pszString);
wprintf(L"Function: GetStringLength2(\"%s\") => %d\n", pszString, nLength);
//
// Call the callback functions exported from a module.
//
// Call int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc);
LPFNMAX lpfnMax = (LPFNMAX)GetProcAddress(hModule, "CompareInts");
if (lpfnMax == NULL)
{
wprintf(L"CompareInts cannot be found (Error: 0x%08lx)\n", GetLastError());
goto Cleanup;
}
int max = lpfnMax(2, 3, &Max);
wprintf(L"Function: CompareInts(2, 3,Max) => %d\n", max);
//
// Use the class exported from a module.
//
// Dynamically-loaded DLL does not allow you to use the class exported
// from the DLL.
Cleanup:
if (hModule)
{
// Attempt to free and unload the library.
wprintf(L"Unload the dynamically-loaded DLL\n");
if (!FreeLibrary(hModule))
{
wprintf(L"FreeLibrary failed w/err 0x%08lx\n", GetLastError());
}
}
// Check whether or not the module is loaded.
fLoaded = IsModuleLoaded(pszModuleName);
wprintf(L"Module \"%s\" is %sloaded\n", pszModuleName, fLoaded ? L"" : L"not ");
return 0;
}
示例工程地址:http://download.csdn.net/detail/x356982611/8071757