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
", pszModuleName, fLoaded ? L"" : L"not ");

	// Dynamically load the library.
    wprintf(L"Load the library
");
	hModule = LoadLibrary(pszModuleName);
	if (hModule == NULL)
	{
        wprintf(L"LoadLibrary failed w/err 0x%08lx
", GetLastError());
        goto Cleanup;
    }

    // Check whether or not the module is loaded.
	fLoaded = IsModuleLoaded(pszModuleName);
    wprintf(L"Module "%s" is %sloaded
", 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)
", 
            GetLastError());
        goto Cleanup;
    }
	nLength = lpfnGetStringLength1(pszString);
    wprintf(L"Function: GetStringLength1("%s") => %d
", 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)
", 
            GetLastError());
        goto Cleanup;
    }
    nLength = lpfnGetStringLength2(pszString);
    wprintf(L"Function: GetStringLength2("%s") => %d
", 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)
", GetLastError());
        goto Cleanup;
    }
    int max = lpfnMax(2, 3, &Max);
    wprintf(L"Function: CompareInts(2, 3,Max) => %d
", 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
");
        if (!FreeLibrary(hModule))
        {
            wprintf(L"FreeLibrary failed w/err 0x%08lx
", GetLastError());
        }
    }
    
    // Check whether or not the module is loaded.
	fLoaded = IsModuleLoaded(pszModuleName);
    wprintf(L"Module "%s" is %sloaded
", pszModuleName, fLoaded ? L"" : L"not ");

	return 0;
}


演示样例project地址:http://download.csdn.net/detail/x356982611/8071757

原文地址:https://www.cnblogs.com/cynchanpin/p/6962142.html