VS开发C++动态库及其调用程序

2023-11-11

用VS建立一个解决方案,包括两个项目:动态库TestDll和应用程序TestExe。以下详细介绍TestDll动态库配置导出类和函数的方法,以及TestExe应用程序如何调用TestDll和配置项目依赖关系。

一、VS2019创建动态库项目并导出类和函数

1、创建动态库项目TestDll

创建TestDll动态库成功后,VS已经为库项目声明了一个预处理定义符:TESTDLL_EXPORTS(自动生成规则:项目名称大写+下划线+EXPORTS):

添加global.h头文件,利用预处理定义TESTDLL_EXPORTS增加类导出符和函数导出符,如下所示:

#pragma once
//导出类:如果有预定义,就是导出的,否则就是导入的宏
#ifdef TESTDLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API__declspec(dllimport)
#endif
 
//导出函数:如果有预定义,就是导出的,否则就是导入的宏
#ifdef TESTDLL_EXPORTS
#define DLL_API_C extern "C" __declspec(dllexport)
#else
#defineDLL_API_C extern "C" __declspec(dllimport)
#endif
 
//导出函数
DLL_API_C int calculate(int x, int y);

global.h文件,定义了DLL_API是导出类的声明符,DLL_API_C是导出函数的声明符,头文件最后还添加了一个caculate函数导出声明,caculate函数定义可在主函数的cpp文件中实现。

另外,TestDll项目添加了Shape父类,Circle和Square子类,这几个类的介绍可参见《C++虚函数多态和纯虚函数多态的经典用法》,这几个类以及整个解决方案可免费下载。TestDll项目组成如下所示:

2、导出Circle、Square类和calculate()函数

只有导出类和函数才能被其他程序调用。首先导出Circle类,修改Circle.h头文件

#pragma once
#include "global.h"
#include "Shape.h"
class DLL_API Circle:public Shape
{
public:
    Circle(){};
    Circle(std::string strName):Shape(strName) {};
    ~Circle(){};
    void init() override;
    void setRadius(int iRadius);
    virtual float getArea() override;
    virtual int getRadius() override;
private:
    int _iRadius;
};

由上可见,Circle类增加DLL_API即可导出;

同理,Square类增加DLL_API导出。

然后在动态库主函数cpp文件中增加calculate()函数的实现:

#include "pch.h"
#include "global.h"
DLL_API_C int calculate(int x, int y) {
   return x * y;
}
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;
}

由上可见,calculate()函数的实现也要由导出符DLL_API_C声明。

二、VS2019创建应用程序并调用动态库

1、创建TestExe应用程序

在解决方案中添加新控制台应用项目TestExe。解决方案中包含两个项目,一个是TestDll库项目,一个是TestExe应用程序项目,如下所示:

在TestExe.cpp应用程序文件中添加如下代码,包含Circle.h和Square.h头文件(global.h包含于两个类头文件,因此也包含了calculate()导出函数的声明),即可调用TestDll库的导出类Circle、Square和导出函数calculate():

#include <iostream>
#include "Circle.h"
#include "Square.h"
int main()
{
   std::cout << "Call the dll function caculate. " << std::endl;
   int iZ =caculate(2, 10);
   std::cout << "caculate iZ:" << iZ << std::endl;
   std::cout << "Please input a number :1 or 2. 1 means a circleshape,2 means a square shape. " << std::endl;
   intiShapeType = 0;//1或者2分别代表圆和正方形
   std::cin >>iShapeType;
   Shape* pShape= nullptr;
   if(iShapeType == 1)
       pShape = new Circle("Circle");
   else if (iShapeType == 2)
       pShape = new Square("Square");
   else {
       std::cout << "Input error.";
       return 0;
   }
   pShape->init();
   float fArea =pShape->getArea();
   std::cout <<pShape->getName() << " Area:" << fArea << std::endl;
   int iPosX,iPosY;
   pShape->getPos(iPosX, iPosY);
   std::cout <<pShape->getName() << " CenterPosX:" << iPosX << " CenterPosY:" << iPosY << std::endl;
   intiSideLen = pShape->getSideLength();
   std::cout <<pShape->getName() << " SideLength:" << iSideLen << std::endl;
   int iRadius= pShape->getRadius();
   std::cout <<pShape->getName() << " Radius:" << iRadius << std::endl;
}

此时还需要配置TestExe,包含TestDll的所需头文件,以及显式配置TestDll库的导入。

2、配置TestExe调用TestDll库

(1)配置包含TestDll库的头文件路径

C/C++——>常规——>附加包含目录,填写相对路径:..\TestDll

(2)链接库设置,配置链接TestDll

TestDll库项目编译后生成TestDll.lib和TestDll.dll两个文件,采用 TestExe应用程序显式链接lib的配置方式,首先链接器——>常规——>附加库目录:配置TestDll的lib库编译生成路径。

其次添加TestExe应用程序的lib依赖,链接器——>输入——>附加依赖项:添加TestDll.lib。

至此TestExe应用程序项目配置调用动态库完毕,可以编译运行了(由于两个项目在一个解决方案中,TestDll生成的dll文件与TestExe的exe文件在同一个目录下,exe可直接运行)。另外,可设置TestExe项目依赖于TestDll项目(TestExe项目右键——>生成依赖项——>项目依赖项),每次TestExe重编译时,如果TestDll已经改动,会先编译TestDll后编译TestExe。

CSDN免费下载: C++动态库创建和应用程序调用动态库的源码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VS开发C++动态库及其调用程序 的相关文章

  • IIS应用程序池回收+quartz调度

    我正在 IIS 7 5 上运行一个 Web 应用程序 它需要偶尔回收 否则内存使用情况会失控 这是我正在研究的问题 当它回收时 它实际上不会运行 直到另一个请求到来 而quartz不会运行 有没有办法让IIS在回收应用程序池后立即自动启动1
  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • Poco c++Net:Http 从响应中获取标头

    我使用 POCO C Net 库进行 http 我想尝试制定持久缓存策略 首先 我认为我需要从缓存标头中获取过期时间 并与缓存值进行交叉检查 如果我错了 请告诉我 那么我如何从中提取缓存头httpResponse 我已经看到你可以用 Jav
  • 在路由mvc 4中添加公司名称

    我一直在尝试为 Facebook 等用户提供在 URL 中添加公司名称的选项 http localhost 50753 MyCompany Login 我尝试过不同的网址 但没有成功 routes MapRoute name Default
  • std::call_once 可重入且线程安全吗?

    std call once http en cppreference com w cpp thread call once是线程安全的 但它也是可重入的吗 我使用 VS2012 调试和发布 进行的测试表明 调用std call once从单
  • 是否存在指向不同类型的指针具有不同大小的平台?

    C 标准允许指向不同类型的指针具有不同的大小 例如sizeof char sizeof int 是允许的 但是 它确实要求如果将指针转换为void 然后转换回其原始类型 它必须与其原始值进行比较 因此 从逻辑上来说 sizeof void
  • Gwan C#,如何获取HTTP标头?

    我需要它来重写 url 以了解我正在处理哪个友好的 url 用于用户代理和其他东西 EDIT public class Gwan MethodImplAttribute MethodImplOptions InternalCall exte
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 增强精神、递归和堆栈溢出

    为什么下面的代码在运行时崩溃 它会给出堆栈溢出错误 include
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 为什么 Cdecl 调用在“标准”P/Invoke 约定中经常不匹配?

    我正在开发一个相当大的代码库 其中 C 功能是从 C P Invoked 的 我们的代码库中有很多调用 例如 C extern C int stdcall InvokedFunction int 使用相应的 C DllImport CPlu
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • 使用 GCC 生成可读的程序集?

    我想知道如何使用GCC http en wikipedia org wiki GNU Compiler Collection在我的 C 源文件中转储机器代码的助记符版本 这样我就可以看到我的代码被编译成什么 你可以使用 Java 来做到这一
  • .NET 4 的条件编译[重复]

    这个问题在这里已经有答案了 可能的重复 条件编译和框架目标 https stackoverflow com questions 2923210 c sharp conditional compilation and framework ta
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • CUDA 8 编译错误 -std=gnu++11

    我正在尝试转换一些代码以使用 CUDA 并且我认为我遇到了兼容性问题 我们使用CMake 这些是我使用的 gcc 和 CUDA 版本 gcc version gcc Ubuntu 5 4 0 6ubuntu1 16 04 5 5 4 0 2
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc
  • 为什么匹配模板类上的部分类模板特化与没有模板匹配的另一个部分特化不明确?

    这个问题可能很难用标题中的句子来描述 但这里有一个最小的例子 include

随机推荐

  • docker命令、操作、部署服务器

    亲测有效 买了腾讯云 安装了centos8 0 进行docker操作 视频教学 https www bilibili com video BV1CJ411T7BK p 28 spm id from pageDriver vd source
  • Mysql驱动包下载

    第一步 下载地址 MySQL Download Connector J 第二步 第三步 第四步 解压 第五步 找到驱动包 放入项目使用即可
  • 知识图谱简介

    1 什么是知识图谱 知识图谱的概念是由谷歌公司于2012年5月17日首次提出 旨在描述客观世界的概念 实体 事件及其之间的关系 并作为构建下一代智能化搜索引擎的核心基础 通俗地讲 知识图谱就是把所有不同种类的信息连接在一起而得到的一个关系网
  • 如何最高效实现手机~电脑端文件传输?

    平常使用电脑办公的时候 经常会有把手机上的文件传到电脑或把电脑上的文件分发给局域网 内网 的各个伙伴的情况 通常我们会选择使用QQ或微信的文件传输功能来实现 但是当文件比较大 比较多时 就无法发送了 再者每次通过文件助手来发送文件时 其本质
  • 软件测试项目管理平台

    系统组成 STM软件测试项目管理系统采用C S软件架构 是一个多人协同工作的环境 数据库服务器端部署SQL Server数据库 包括人力资源数据库 设备资源数据库 项目管理数据库 测试项目数据库 历史归档数据库 客户端部署软件测试项目管理系
  • 从瞳孔的扩张收缩提取大脑EEG的delta,theta,alpha,beta,gamma等信号信息

    展示得到的结果图 直接上代码 import pandas as pd from scipy signal import find peaks from scipy fftpack import fft fftshift ifft impor
  • 【C语言刷LeetCode】300. 最长上升子序列(M)

    给定一个无序的整数数组 找到其中最长上升子序列的长度 示例 输入 10 9 2 5 3 7 101 18 输出 4 解释 最长的上升子序列是 2 3 7 101 它的长度是 4 说明 可能会有多种最长上升子序列的组合 你只需要输出对应的长度
  • (个人)AR电子书系统创新实训第二周(1)

    从头实现一个识别二维码的Unity项目 通过上次大致了解了ZXing Net的基本使用方法后 此次我决定使用它和unity制作一个简单的测试项目 以检验其功能是否满足要求 具体步骤如下 1 创建Unity项目 将zxing unity dl
  • 第十一届蓝桥杯 ——矩阵

    问题描述 把 1 2020 放在 2 1010 的矩阵里 要求同一行中右边的比左边大 同一列中下边的比上边的大 一共有多少种方案 答案很大 你只需要给出方案数除以 2020 的余数即可 答案提交 这是一道结果填空题 你只需要算出结果后提交即
  • 【DOS编程整理】

    以下文章来源 DOS编程大全 KingAntY的专栏 CSDN博客 dos编程 目录 第一章 批处理基础 第一节 常用批处理内部命令简介 1 REM 和 2 ECHO 和 3 PAUSE 暂停 4 ERRORLEVEL 5 TITLE 设置
  • C# 3D拾取技术,本地存储,角色控制器

    1 3D拾取技术 1 从原点发射一条射线 void Update 定义一条射线 起点为Vector3 zero 终点为物体坐标 Ray ray new Ray Vector3 zero transform position 定义一个光线投射
  • 给apk手动签名

    用Android studio生成签名文件然后用命令签名 先要对齐apk zipalign v p 4 需要签名apk 输出后的apk jarsigner verbose keystore 签名文件 jks storepass 密码 key
  • linux安装mysql 8.0.20(正式环境)

    安装之前需要确认机器上是否安装过mysql如果已经安装过 需要清理掉 1 检查是否已经安装过mysql rpm qa grep mysql 如果环境中有遗留mysql则执行删除命令 rpm e nodeps mysql xxxxxxxxx
  • 覆盖拦截器栈里特定拦截器的参数

  • 一文带你了解ViewModel

    Lifecycle库可以有效避免内存泄漏和解决常见的Android生命周期难题 1 引言 ViewModel属于lifecycle 生命周期感知型组件 中的一员 通常与LiveData DataBinding一起使用 它们是MVVM架构的重
  • HCIP——IPV6实验

    一 实验要求 1 两个局域网基于6to4tunnel可达 2 R1可以访问R3的环回 二 实验拓扑结构 三 实验过程 1 配置公网IP地址以及缺省路由 R2 r2 int g0 0 1 r2 GigabitEthernet0 0 1 iP
  • JavaScript Set()对象 实现去重

    Set 对象里的值具有唯一性 我们可以利用这个特性进行数组去重 let arr 2 2 2 8 8 55 55 0 1 0 1 i i null null undefined undefined NaN NaN let newArr fun
  • Navicat Premium 12

    一 破解 1 下载安装Navicat Premium 12 2 解压破解补丁 选择对应版本 这里选的是简体中文64位 3 打开所选目录 复制里面文件 4 将复制的文件粘贴到Navicat Premium 12的安装根目录 5 打开软件即可无
  • 小米怎么快速回到顶部_打开小米这3个设置,手机越用越好用啦!你现在还不知道吗?...

    手机天天都在用 但是你对你的小米手机足够了解吗 小米手机有很多好用的功能设置 比如以下这3个 打开小米手机下面这3个设置 你的小米手机会越来越好用 下面就一起来看看吧 全面屏手势 第一个设置是小米的 全面屏手势 开启小米手机的 全面屏手势
  • VS开发C++动态库及其调用程序

    用VS建立一个解决方案 包括两个项目 动态库TestDll和应用程序TestExe 以下详细介绍TestDll动态库配置导出类和函数的方法 以及TestExe应用程序如何调用TestDll和配置项目依赖关系 一 VS2019创建动态库项目并