Visual Studio 2022封装C代码为x64和x86平台动态库

2023-12-16 23:55:03

1.引言

本文介绍如何使用Visual Studio 2022C语言函数封装成x64x86平台上使用的动态链接库(dll文件)并生成对应的静态链接库(lib文件),以及如何在C++程序中调用生成的dll。

程序下载:

2.示例C语言程序

假设需要开发一个动态链接库,实现复数的四则运算,定义如下头文件ComplexCal.h和源码文件ComplexCal.c。

(1)ComplexCal.h

#ifndef COMPLEXCAL_H
#define COMPLEXCAL_H
//定义复数结构体
typedef struct {
    double real;
    double imag;
} Complex;
//复数加法
Complex add(Complex a, Complex b);
//复数减法
Complex subtract(Complex a, Complex b);
//复数乘法
Complex multiply(Complex a, Complex b);
//复数除法
Complex divide(Complex a, Complex b);
#endif //COMPLEXCAL_H

(2)??ComplexCal.c

#include "CompplexCal.h"
/**
 * 复数加法
 * @param a Complex结构体
 * @param b Complex结构体
 * @return Complex结构体
 */
Complex add(Complex a, Complex b) {
    Complex result;

    result.real = a.real + b.real;
    result.imag = a.imag + b.imag;

    return result;
}
/**
 * 复数减法
 * @param a  Complex结构体
 * @param b  Complex结构体
 * @return  Complex结构体
 */
Complex subtract(Complex a, Complex b) {
    Complex result;

    result.real = a.real - b.real;
    result.imag = a.imag - b.imag;

    return result;
}
/**
 * 复数乘法
 * @param a  Complex结构体
 * @param b  Complex结构体
 * @return  Complex结构体
 */
Complex multiply(Complex a, Complex b) {
    Complex result;

    result.real = (a.real * b.real) - (a.imag * b.imag);
    result.imag = (a.real * b.imag) + (a.imag * b.real);

    return result;
}

/**
 * 复数除法
 * @param a Complex结构体
 * @param b Complex结构体
 * @return Complex结构体
 */
Complex divide(Complex a, Complex b) {
    Complex result;
    double denominator = b.real * b.real + b.imag * b.imag;

    result.real = (a.real * b.real + a.imag * b.imag) / denominator;
    result.imag = (a.imag * b.real - a.real * b.imag) / denominator;

    return result;
}

3.创建Visual Studio 动态链接库工程并定义宏指令

3.1 创建dll工程

接下来说明如何创建Visual Studio动态链接库工程并编写相应的dll封装头文件。新建complex_cal文件夹,然后打开Visual Studio,在该目录下创建dll工程,如动图所示,然后将将示例头文件和源码文件复制到complex_cal/ComplexCal文件夹(Visual Studio解决方案文件ComplexCal.sln文件所在文件夹)内。

Visual Studio会预先创建?framework.hpch.hpch.cdllmain.cpp等4个模板文件,其中pch.h为预编译标头文件,这里用不上这些模板文件,可以将其移除或者删除。

??3.2 添加示例头文件和源码文件到解决方案内

首先需要添加ComplexCal.h(添加到头文件下)ComplexCal.c(添加到源文件下)文件到Visual Studio解决方案资源管理器内,才能让Visual Studio加载。

3.3 取消使用预编译标头

另外还需取消使用预编译标头,否则将出现C1010错误:

?取消方法在项目属性/C/C++/预编译头选项下选择不使用预编译头,如下所示:

注意在头部配置和平台上选中所有配置所有平台

3.4?在头文件中添加dll宏指令

ComplexCal.h中添加以下宏,导出函数给外部调用:



#ifndef COMPLEXCAL_H
#define COMPLEXCAL_H
//定义复数结构体
typedef struct {
    double real;
    double imag;
} Complex;

//dll入口宏指令
#ifndef  COMPLEXCAL_H_API_EXPORTS
#define  COMPLEXCAL_H_API_EXPORTS __declspec(dllexport)
#endif // !COMPLEXCAL_H_API_EXPORTS


//根据不同平台定义函数调用堆栈修饰宏
#ifdef _WIN64 || _M_X64
   //x64平台
 #define dll_std_call __stdcall
#elif _WIN32 || _M_IX86
  // x86平台
#define dll_std_call __cdecl
#endif

// 一般用于将C++代码以标准C形式输出(即以C的形式被调用)
// 告诉编译器下面大括号括起来的函数是c语言函数(因为c++和c语言对函数的编译转换不一样,主要是c++中存在重载)
#ifdef __cplusplus        
extern"C" {                 
#endif
//复数加法
    __declspec(dllexport) Complex dll_std_call  add(Complex a, Complex b);
//复数减法
    __declspec(dllexport) Complex dll_std_call subtract(Complex a, Complex b);
//复数乘法
    __declspec(dllexport) Complex dll_std_call multiply(Complex a, Complex b);
//复数除法
    __declspec(dllexport) Complex dll_std_call divide(Complex a, Complex b);
#ifdef __cplusplus
}
#endif
#endif //COMPLEXCAL_H

3.5? 选择目标平台并生成解决方案来生成dll

在Visual Studio工具栏上选择dll的构建配置和目标平台,例如Debug和x64。在Visual Studio中,Debug和Release是两种不同的构建配置。它们之间的主要区别在于编译器如何优化代码并生成可执行文件。

在Debug模式下,编译器会生成包含调试符号的二进制文件。这些符号可以用于在代码中设置断点、跟踪变量值等操作,以便进行调试。此外,编译器通常会关闭优化,以便使得调试更容易。

在Release模式下,编译器通常会启用各种优化,以生成更快、更紧凑的代码。这些优化可能会包括删除未使用的代码、内联函数、循环展开和其他技术。此外,由于没有调试符号,生成的文件大小也比Debug模式下的要小得多。

?然后运行工具栏生成/生成解决方案来生成dll。

对于x64平台,生成的dll文件位于解决方案(.sln文件)同目录的x64文件夹下,对于Debug构建配置,位于x64/DebugRelease构建配置位于x64/Release。对于x86平台的Debug构建配置,则位于解决方案文件同目录的Debug文件夹,x86平台的Release构建配置则位于解决方案文件同目录的Release文件夹。

?打开上述目录,其中的ComplexCal.dllComplexCal.lib即我们需要的dll文件,其它文件为编译和链接所需的中间文件。

4.在C++程序中引用动态库

4.1 演示工程配置

创建C++控制台应用,测试生成的复数运算dll。首先使用Visual Studio创建一个控制台应用工程,命名为ComplexCalApplication

将上述生成的dlllib文件以及ComplexCal.h头文件复制到解决方案文件ComplexCalApplication.sln所在目录的include文件夹下,这里以X64_Release为例。

然后添加ComplexCal.h头文件到解决方案资源管理器的头文件下,让Visual Studio能发现该文件。还需在项目属性->C/C++->常规选项下添加include文件夹为附加包含夹,以让链接器能发现并链接dlllib文件:

另外定义生成后事件,让Visual Studio自动复制dll文件到可执行文件所在目录,避免出现dll丢失错误。生成后事件指令如下:

xcopy /y "$(ProjectDir)\include\*.dll" "$(TargetDir)"

上述命令表示在生成结束后自动将 include文件夹下的dll文件复制到可执行文件所在目录内。在项目属性中定义生成后事件的方法如下:

4.2 dll调用

在C++程序中调用dll以下几个步骤:

  1. 将 DLL 的头文件包含到应用程序中。
  2. 定义生成后事件将dll文件复制到可执行文件所在文件夹下。

如代码所示:

#include <iostream>
//引入dll头文件
#include "include/ComplexCal.h"
int main()
{
    Complex a, b, sum, difference;

    std::cout << "Enter the real and imaginary parts of the first complex number: ";
    std::cin >> a.real >> a.imag;

    std::cout << "Enter the real and imaginary parts of the second complex number: ";
    std::cin >> b.real >> b.imag;

    sum = add(a, b);
    difference = subtract(a, b);

    std::cout << "Sum: " << sum.real << " + " << sum.imag << "i" << std::endl;
    std::cout << "Difference: " << difference.real << " + " << difference.imag << "i" << std::endl;

    return 0;

}

文章来源:https://blog.csdn.net/anbuqi/article/details/135036389
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。