C/C++ DLL 動態鏈接庫的開發與示例詳解

簡介

介紹 QT6,DLL 動態鏈接庫的開發,開發示例

詳細

DLL 入口函數

DllMain 是每個 dll 的入口函數,可以寫,也可以不寫,不影響其他庫函數運行。如果使用此函數需要包含頭文件#include <objbase.h>

BOOL WINAPI DllMain(HANDLE hModule, // dll 實例句柄, 也可以記作 HINSTANCEDWORD dwReason, // dll 當前所處狀態LPVOID ljReserved // 保留參數,和 dll 的狀態相關,使用較少
);

入口函數定義示例:

BOOL WINAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID ljReserved)
{switch (dwReason) {case DLL_PROCESS_ATTACH: // 進程加載 dll 時觸發qDebug() << "DLL_PROCESS_ATTACH trick...";break;case DLL_PROCESS_DETACH: // 進程卸載 dll 時觸發qDebug() << "DLL_PROCESS_DETACH trick...";break;case DLL_THREAD_ATTACH: // 線程加載 dll 時觸發qDebug() << "DLL_THREAD_ATTACH trick...";break;case DLL_THREAD_DETACH: // 線程卸載 dll 時觸發qDebug() << "DLL_THREAD_DETACH trick...";break;}return true;
}

DLL 自定義庫函數

導出函數

導出函數,即為使用 dll 庫時候,可以從外部調用到的函數。不聲明為導出函數,只能在庫內部調動,外部無法調用到未進行導出函數聲明的函數。其他關鍵字的說明如下:

extern "[C/C++]" __declspec(dllexport) void [CALLBACK] test(); // 簡單庫函數聲明導出函數示例
  • extern "C" 表示在用 C++ 代碼調用 dll 庫時候,需要聲明。是由于 C 和 C++ 編譯器對同一函數編譯后,生成的符號表有差異,導致調用時候可能有異常,加上此聲明,表示按照C語言的方式進行函數調用。如果只在 C 語言中進行使用,那么可以不寫此關鍵字。

  • __declspec(dllexport) 聲明函數為導出函數。

  • CALLBACK 如果自定義函數是 windows 窗口函數,還需要在函數聲明時候使用 (表示可以被操作系統進行調用)。

導出類

幾乎所有的Windows平臺的C++編譯器都支持從DLL中導出C++類,導出C++類與導出C函數非常相似。如果需要導出整個類,就是在類名前面使用說明符。

#define XYZAPI __declspec(dllexport)
// 導出整個 CXyz 類
class XYZAPI CXyz
{
public:int Foo(int n);
}// 僅導出 Foo 方法
class CXyz
{
public:XYZAPI int Foo(int n);
}

默認情況下,C++編譯器使用 __thiscall 的調用約定,由于不同的編譯器使用的名字修飾約定不同,因此導出的 C++ 類只能被相同的編譯器和相同版本的編譯器使用。

導出類使用示例:

#include "XyzLibrary.h"
CXyz xyz;
xyz.Foo(21);

但是在以下情況下,編譯器會警告你未導出基類和數據成員,如果要成功導出C++類,開發人員必須導出所有相關的基類和所有用于定義數據成員的類,

class Base {};
class Data {};
// 警告:未導出基類
class __declspec(dllexport) Child : Base
{...
private:Data m_data; // 警告:未導出成員
}
優缺點

優點:該導出方式導出的類與 C++ 其他類的使用幾乎相同。

缺點:

  1. 后期維護比較麻煩,導出的類可能產生非常大的依賴,導致代碼耦合度高
  2. 必須保證使用同一種編譯器,導出類的本質是導出類中的函數,因為語法上直接導出了類,沒有對函數的調用方式,重命名進行設置,導致產生的 dll 沒有通用性
  3. DLL HELL 問題

DLL Hell 是指當多個應用程序試圖共享一個公用組件(如某個動態連接庫(DLL)或某個組件對象模型(COM)類)時所引發的一系列問題。最典型的情況是,某個應用程序將要安裝一個新版本的共享組件,而該組件與機器上的現有版本不向后兼容。雖然剛安裝的應用程序運行正常,但原來依賴前一版本共享組件的應用程序也許已無法再工作。

**“Side by side” 是在同一臺機器上同時運行不同版本的相同組件的能力。**使用支持并列的組件,編程人員不必努力維護嚴格的向后兼容,因為不同的應用程序自由使用某個共享組件的不同版本。

導出變量
通過 __declspec 導出聲明
// 導出/導入變量聲明
DLL_SAMPLE_API extern int DLLData;
用模塊定義文件(.def)進行導出聲明
LIBRARY DLLSample
DESCRIPTION "my simple DLL"
EXPORTSDLLData DATA  ;DATA表示這是數據(變量)
導出變量使用

導出變量的隱式使用示例:

#include <stdio.h>
#include "DLLSample.h"
#pragma comment(lib,"DLLSample.lib")int main(int argc, char *argv[])
{printf("%d ", DLLData);return 0;
}

導出變量的顯示使用示例:

#include <iostream>
#include <windows.h>int main()
{int my_int;HINSTANCE hInstLibrary = LoadLibrary("DLLSample.dll");if (hInstLibrary == NULL){FreeLibrary(hInstLibrary);}// 獲取變量值my_int = *(int*)GetProcAddress(hInstLibrary, "DLLData");if (dllFunc == NULL){FreeLibrary(hInstLibrary);}std::cout<<my_int;std::cin.get();FreeLibrary(hInstLibrary);return(1);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86226.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86226.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86226.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在 CentOS 7 上基于 Docker 的 LNMP 部署 Hexo

時間起因是因為之前BLOG沒有備份數據都丟失了,今天在和朋友聊天的時候討論到到底使用Hexo還是用Halo?最后還是想熟悉下這兩種博客的架設和部署方式,每次部署都有各種不同的問題,旨在提升自己的學習認知。以此有機會得到更多大佬們的指導~ 因為我是在 CentOS 7 服務器上使用…

《Go小技巧易錯點100例》第三十六篇

本期分享&#xff1a; 1.使用gops獲取正在運行的Go進程 2.將靜態文件編譯到Go程序中 3.Go語言通過多重賦值實現變量值交換 使用gops獲取正在運行的Go進程 在 Go 語言開發中&#xff0c;進程診斷和性能分析是保障服務穩定性的關鍵環節。Google 開源的 gops [https://github.…

Idea新UI

輕松上手Idea新UI&#xff1a;開啟高效編程新體驗 在軟件開發領域&#xff0c;IntelliJ IDEA一直以其強大的功能和出色的性能深受開發者喜愛。而其推出的new ui&#xff0c;更是為我們帶來了全新的操作體驗&#xff0c;進一步提升了開發效率。今天&#xff0c;就來詳細講講如何…

QML\QtQuick\QtWidgets適合的場景及其優缺點

在Qt框架中&#xff0c;QML、QtQuick和QtWidgets是三種不同的UI開發技術&#xff0c;各有其適用場景和優缺點。以下是它們的對比分析&#xff1a; 1. QtWidgets 適用場景&#xff1a; 傳統的桌面應用程序&#xff08;Windows/macOS/Linux&#xff09;。 需要復雜控件&#xf…

Spring Boot 2.x 項目搭建 (二)

因為Spring Boot 2.x 項目搭建 &#xff08;一&#xff09;訪問 start.spring.io 或通過IDE&#xff08;如IntelliJ IDEA&#xff09;的Spring Initializr向導創建項目時&#xff0c;只能使用jdk17以上的版本&#xff0c;這里我需要兼容老項目需要JDK1.8&#xff0c;所以進行一…

Python 前端框架/工具合集

前言 Python 本身并不是為前端開發而設計的語言&#xff0c;但確實有一些 Python 框架可以“變相”地用于前端開發&#xff0c;比如生成 HTML、控制前端頁面邏輯&#xff0c;甚至可以直接運行在瀏覽器中。 目標 本文將對常見的使用python實現的前端框架&#xff0c;先做一個…

Swagger 在 Spring Boot 中的詳細使用指南

Swagger 是一個強大的 API 文檔生成工具&#xff0c;在 Spring Boot 項目中主要通過 springdoc-openapi 庫實現。下面我將詳細講解 Swagger 的配置、注解使用和高級功能。 一、基礎配置 1. 添加依賴 在 pom.xml 中添加&#xff1a; xml 復制 下載 運行 <dependency&…

群暉如何開啟及使用ssh:小白用戶上手指南-家庭云計算專家

最近很多用戶希望提供群暉下onlyoffice的安裝服務,但是很多都是萌新小白,不知道怎么啟用ssh和使用ssh客戶端.這里提供簡單的方法,統一答復: 重要的事情說3遍:一定不要自己發揮,全部按說明的來;一定要在內網環境用內網ip訪問;不要用域名和端口號,謝謝各位萌新了!!! 一、ssh啟用…

Ubuntu查看與切換顯示管理器(已測試ubuntu20,ubuntu24)

一級標題 顯示管理器是用戶使用圖形化的登錄界面。 當用戶成功輸入用戶名和密碼后&#xff0c;即可開始使用圖形化界面會話。gdm3和 lightdm 都是顯示管理器。 它們提供了圖形化登錄并處理用戶身份驗證。 查看正在使用的顯示管理器&#xff1a; cat /etc/X11/default-displa…

ROS 2 中 Astra Pro 相機與 YOLOv5 檢測功能編譯啟動全記錄

先記錄大概主要流程&#xff0c;后期有時間了再完善細節以及附上截圖 一、編譯 Astra Pro 相機功能包 1. 清理并編譯相機包 cd ~/Astra_ws rm -rf build/astra_camera install/astra_camera # 清理舊編譯 colcon build --packages-select astra_camera --parallel-workers …

當實體類名和數據庫表列名不一致時不能封裝數據的解決辦法

1. <resultMap> 是什么&#xff1f; 作用&#xff1a;<resultMap> 用來定義數據庫表字段和Java實體類屬性之間的對應關系。 為什么需要&#xff1f; 數據庫字段通常用下劃線命名&#xff08;如 brand_name&#xff09;&#xff0c;而Java類屬性用駝峰命名&#…

window系統上labelImg的安裝與使用

一、window上安裝Anaconda 下載&#xff1a;https://repo.anaconda.com/archive/選擇版本&#xff0c;此次選擇的是Anaconda3-2025.06-0-Windows-x86_64.exe雙擊安裝在 Windows 搜索欄中輸入 Anaconda Prompt 并打開。 二、安裝pyton3.8 wondow環境 在 Windows 搜索欄中輸入…

SSE 流與普通 HTTP 響應的區別

1. 連接特性 特性普通 HTTP 響應SSE 流連接持續時間一次性&#xff0c;請求-響應后立即關閉持久連接&#xff0c;保持打開狀態通信方向單向 (客戶端→服務器→客戶端)單向 (服務器→客戶端)數據格式完整響應體流式文本數據 (text/event-stream) 2. 數據傳輸方式 普通 HTTP 響…

Proteus仿真51單片機控制L298N PWM電機調速

51單片機概述 51單片機是指Intel公司開發的MCS-51系列單片機及其兼容產品&#xff0c;是應用最廣泛的8位單片機系列之一。其名稱來源于該系列的第一款芯片8051。 主要特點&#xff1a; 8位CPU&#xff1a;處理數據寬度為8位 哈佛結構&#xff1a;程序存儲器和數據存儲器分開…

批量將exb文件轉為pdf的實用工具

最近在工作中遇到了一個棘手的問題&#xff1a;需要將大量CAXA電子圖板(.exb)格式的圖紙文件轉換為PDF格式以便于共享和查閱。手動一個個打開轉換不僅效率低下&#xff0c;而且容易出錯。于是&#xff0c;我決定開發一個批量轉換工具來解決這個問題。 使用效果 在實際使用中&…

從C++編程入手設計模式——命令模式

從C編程入手設計模式——命令模式 ? 命令模式是一個用指令封裝請求的優雅方法。換而言之&#xff0c;對于一個復雜的系統&#xff0c;當我們發現&#xff0c;使用一系列的指令&#xff08;Command&#xff09;來操作對象的時候&#xff0c;這個設計模式就會顯得非常的實用。我…

【基礎篇-消息隊列】——如何通過網絡傳輸結構化的數據( 序列化與反序列化)

目錄 一、引入前提二、選擇哪種序列化實現2.1、選擇哪種序列化實現需要權衡的幾個因素2.2、如何選擇哪種序列化實現三、實現高性能的序列化和反序列化四、小結本文來源:極客時間vip課程筆記 一、引入前提 在 TCP 的連接上,它傳輸數據的基本形式就是二進制流,也就是一段一段的…

LINUX 622 SAMBA

SAMBA案例 user01通過wondows或linux在/samba/share 中創建、刪除文件 環境配置 samba安裝 [rootsamba caozx26]# yum install samba -y 已加載插件&#xff1a;fastestmirror, langpacks Loading mirror speeds from cached hostfile 正在解決依賴關系 --> 正在檢查事務…

Linux Sonic Agent 端部署(詳細版)(騰訊云)

&#xff08;因為服務器是Linux的&#xff0c;只是安裝了&#xff0c;并沒有驗證&#xff09; 1、編輯docker-compose.yml文件 在Services下添加Agent sonic-agent:image: "sonicorg/sonic-agent-linux:v2.7.2"environment:- SONIC_SERVER_HOST${SONIC_SERVER_HOST…

SpringCloud學習筆記 - 2、關于Cloud各種組件的停更/升級/替換

文章目錄 前言SpringCloud是什么&#xff1f;SpringCloud 在 2018 年&#xff0c;技術體系SpringCloud 在 2020 年&#xff0c;“移除”了技術體系SpringCloud 在 2024 年&#xff0c;移除了技術體系SpringCloud 2024年&#xff0c;技術體系服務注冊與發現 模塊1、Eureka2、Con…