C++创建一个动态链接库

C++创建一个动态链接库
动态链接库是一个模块,它包含了一些函数和数据,能够被其他模块进行调用(其他程序或DLL)。

下面演示如何将函数,数据和类导出供其他可执行文件调用。

导出的数据,函数,和类如下

// Global Data
int g_nVal1
int g_nVal2


// Ordinary Functions
int __cdecl GetStringLength1(PCWSTR pszString);
int __stdcall GetStringLength2(PCWSTR pszString);


// Callback Function
int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc)


// Class
class CSimpleObject
{
public:
    CSimpleObject(void);  // Constructor
    virtual ~CSimpleObject(void);  // Destructor
      
    // Property
    float get_FloatProperty(void);
    void set_FloatProperty(float newVal);


    // Method
    HRESULT ToString(PWSTR pszBuffer, DWORD dwSize);


    // Static method
    static int GetStringLength(PCWSTR pszString);


private:
    float m_fField;
};

有两种方法可以从DLL中导出数据
1.使用.DEF文件进行导出
模块定义文件(.DEF)是一个纯文本文件,包括了一个或多个模块的声明,用来描述DLL的属性。
2.使用导出符号__declspec(dllexport) 
A 使用.DEF导出的具体实现方法是如下

1.首先在头文件中声明导出数据和函数,然后在cpp中进行定义

    int g_nVal1;
    int /*__cdecl*/ GetStringLength1(PCWSTR pszString)
    int __stdcall GetStringLength1(PCWSTR pszString)
    int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc)
2.添加一个.DEF文件,名称为CppDynamicLinkLibrary.def。文件的第一行必须是LIBRARY,然后紧跟要导出的DLL的名字,例如CppDynamicLinkLibrary 。接下来导出声明列出将要导出的数据或函数的名字。

   LIBRARY   CppDynamicLinkLibrary
   EXPORTS
   GetStringLength1     @1
   CompareInts          @2
   g_nVal1              DATA
由于在连接过程中DLL工程会调用.def文件,所以我们应该在项目的属性对话框中的Linker/Input 页面将 模块定义文件的值设置为我们刚才创建的那个.def文件。

B 使用__declspec(dllexport)导出符号进行导出

首先在头文件中定义如下预编译块
这样做的目的是使得我们在导入导出的时候更方便,因为我们可以使用SYMBOL_DECLSPEC宏来替代看起来十分繁琐吓人的__declspec(dllexport)导出符号。

    #ifdef CPPDYNAMICLINKLIBRARY_EXPORTS
    #define SYMBOL_DECLSPEC __declspec(dllexport)
    #else
    #define SYMBOL_DECLSPEC __declspec(dllimport)
    #endif


在每个将要导出的数据或函数前都加上SYMBOL_DECLSPEC,这里我们额外添加EXTERN_C(extern “C”)的目的是为了支持我们的模块被C语言或其他动态链接的程序调用。添加这个的意思就是指明使用C的连接方式,在连接的时候函数名不会改变,而不是C++的安全命名法,会改变函数名称。

EXTERN_C SYMBOL_DECLSPEC int g_nVal2;
EXTERN_C SYMBOL_DECLSPEC int /*__cdecl*/ GetStringLength2(PCWSTR pszString);
EXTERN_C SYMBOL_DECLSPEC int __stdcall GetStringLength2(PCWSTR pszString);
class SYMBOL_DECLSPEC CSimpleObject
{
    ...
};

完整代码:

.h

#pragma once

#include <windows.h>

// The following ifdef block is the standard way of creating macros which 
// make exporting from a DLL simpler. All files within this DLL are compiled 
// with the CPPDYNAMICLINKLIBRARY_EXPORTS symbol defined on the command line. 
// This symbol should not be defined on any project that uses this DLL. This 
// way any other project whose source files include this file see 
// SYMBOL_DECLSPEC and SYMBOL_DEF functions as being imported from a DLL, 
// whereas this DLL sees symbols defined with these macros as being exported.

#ifdef CPPDYNAMICLINKLIBRARY_EXPORTS
#define SYMBOL_DECLSPEC __declspec(dllexport)
#define SYMBOL_DEF
#else
#define SYMBOL_DECLSPEC __declspec(dllimport)
#define SYMBOL_DEF      __declspec(dllimport)
#endif


#pragma region Global Data

EXTERN_C SYMBOL_DECLSPEC int g_nVal2;

#pragma endregion


#pragma region Ordinary Functions

SYMBOL_DEF int /*__cdecl*/ GetStringLength1(PCWSTR pszString);

EXTERN_C SYMBOL_DECLSPEC int __stdcall GetStringLength2(PCWSTR pszString);

#pragma endregion


#pragma region Callback Function

// Type-definition: 'PFN_COMPARE' now can be used as type
typedef int (CALLBACK *PFN_COMPARE)(int, int);

// An exported/imported stdcall function using a DEF file
// It requires a callback function as one of the arguments
// Sym: CompareInts
// See: CppDynamicLinkLibrary.cpp
SYMBOL_DEF int __stdcall CompareInts(int a, int b, PFN_COMPARE cmpFunc);

#pragma endregion


#pragma region Class

class SYMBOL_DECLSPEC CSimpleObject
{
public:

    CSimpleObject(void);  // Constructor
    virtual ~CSimpleObject(void);  // Destructor

    // Property
    float get_FloatProperty(void);
    void set_FloatProperty(float newVal);

    // Method
    HRESULT ToString(PWSTR pszBuffer, DWORD dwSize);

    // Static method
    static int GetStringLength(PCWSTR pszString);

private:
    float m_fField;
};

#pragma endregion
.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
.def

LIBRARY   CppDynamicLinkLibrary
EXPORTS
   GetStringLength1     @1
   CompareInts          @2
   g_nVal1              DATA






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白话机器学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值