C++函数的导出与导入
DLL使用
(1)隐式链接到 DLL 的可运行文件在生成时链接到导入库(.lib文件)。
(2)採用显式连接(LoadLibrary和GetProcAddress)时,不须要.lib文件。
函数导出方式
(1)源码中的 __declspec(dllexport) keyword
(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; }
演示样例project地址:http://download.csdn.net/detail/x356982611/8071757
posted on 2017-06-08 12:11 cynchanpin 阅读(2591) 评论(0) 编辑 收藏 举报