C动态库的生成与在Python和QT中的调用方法
目录
一、动态库生成
1)C语言生成动态库
2)c++类生成动态库
二、动态库调用
1)Python调用DLL
2)QT调用DLL
三、存在的一些问题
1)python调用封装了类的DLL可能调用不成功
2)DLL格式不匹配的问题
四、总结
动态库文件在程序开发中运用很常见,但C和C++代码生成动态库文件,以及在使用时均存在一些差异,本文对两者的差异进行了讲解,并通过具体的实例加以说明。实例均在Windows系统下进行,Linux系统下的实现一样。
一、动态库生成
1)C语言生成动态库
我们直接新建一个记事本文件,在文件中输入如下代码。写一个简单的加法函数,函数返回相加的结果,然后将记事本文件保存为myC.c文件,名称随意,扩展名为c。
#include<stdio.h>int add(int a, int b)
{
return a+b;
}
然后使用win+r键 ,输入“cmd”打开命令窗口,使用cd /d E:\Tem,将工作目录切换到myC.c文件存放的E:\Tem路径下。如下图所示。

然后在命令行中输入:"gcc -shared -o myC.dll myC.c" ,执行该命令就可以在当前路径下得到动态库文件myC.dll。

![]()
2)c++类生成动态库
C++是面向对象的编程语言,代码文件一般包含.h头文件和.cpp文件。此处使用记事本分别新建两个文件,命名为myclass.h和myclass.cpp。在文件中输入以下代码,实现用一个整数创建一个类,将整数赋给成员变量,并可改变和返回该成员变量的值。
//头文件
// myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H#ifdef BUILD_MYDLL
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endifclass MYDLL_API MyClass {
private:int value;
public:MyClass(int val);~MyClass();int getValue();void setValue(int val);
};// 封装 C 风格的接口函数
extern "C" {MYDLL_API MyClass* CreateMyClass(int val);MYDLL_API int GetValue(MyClass* obj);MYDLL_API void SetValue(MyClass* obj, int val);MYDLL_API void DestroyMyClass(MyClass* obj);
}#endif
//cpp文件
// myclass.cpp
#include "myclass.h"MyClass::MyClass(int val) : value(val) {}MyClass::~MyClass() {}int MyClass::getValue() {return value;
}void MyClass::setValue(int val) {value = val;
}extern "C" {MYDLL_API MyClass* CreateMyClass(int val) {return new MyClass(val);}MYDLL_API int GetValue(MyClass* obj) {return obj->getValue();}MYDLL_API void SetValue(MyClass* obj, int val) {obj->setValue(val);}MYDLL_API void DestroyMyClass(MyClass* obj) {delete obj;}
}
在命令窗口中执行命令“g++ -shared -o myclass.dll -DBUILD_MYDLL myclass.cpp -Wl,--out-implib=libmyclass.a”,可以得到编译完成后的dll文件。
-
-shared:指定生成共享库(DLL)。 -
-o myclass.dll:指定输出的 DLL 文件名。 -
-DBUILD_MYDLL:定义宏,使MYDLL_API被定义为__declspec(dllexport),用于导出函数和类。 -
-Wl,--out-implib=libmyclass.a:生成导入库文件。


二、动态库调用
1)Python调用DLL
ctypes是 Python 标准库中的一个外部函数库,它提供了与 C 语言兼容的数据类型,允许调用动态链接库(DLL)中的函数。在python中具体实现代码如下,程序运行时需要将生成的myC.dll动态库复制到当前python程序文件所在路径下,否则需要在下面文件路径中使用绝对路径。
import ctypes# 加载 myC.dll
dll = ctypes.CDLL("./myC.dll")
dll.add.argtypes = [ctypes.c_int, ctypes.c_int] # 定义函数参数和返回值类型
dll.add.restype = ctypes.c_int
a = dll.add(2, 11)
print(a)
print('--------------------')
2)QT调用DLL
QT调用DLL有动态和静态两种方式。
(1)动态调用
动态调用需要使用到QT的QLibrary类,此处以调用C++生成的动态库为例,具体代码如下。使用QLibrary类时,只需要在代码中用QLibrary类加载相应的DLL文件,并通过定义函数指针的方式取出需要使用的DLL函数。
在此例中,调用DLL中的函数时,首先需要使用DLL中的创建对象函数创建一个类的实例,由于在调用时不能知道DLL类的结构,因此采用QObject *来接收创建对象的指针。
#include <QCoreApplication>
#include <QLibrary>
#include <QDebug>
#include <QObject>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QLibrary myLib("E:/Tem/useDLL/myclass.dll");if (myLib.load()) {// 定义函数指针类型typedef QObject* (*creatFunction)(int);creatFunction create = (creatFunction)myLib.resolve("CreateMyClass");if (create) {// 调用函数QObject* obj = create(3);//创建对象typedef int (*getFunction)(QObject*);getFunction get = (getFunction)myLib.resolve("GetValue");int val = get(obj);qDebug() << "The get is:" << val;typedef void (*setFunction)(QObject*,int);setFunction set = (setFunction)myLib.resolve("SetValue");set(obj,100);val = get(obj);qDebug() << "The set is:" << val;typedef void (*desFunction)(QObject*);desFunction des = (desFunction)myLib.resolve("DestroyMyClass");des(obj);qDebug() << "obj has been deleted.";} else {qDebug() << "Failed to resolve the function.";}}return a.exec();
}
上述代码执行结果:
![]()
(2)静态调用DLL
当使用静态调用方法时,需要将生成的DLL动态库和对应的.h头文件拷贝到工程目录下。然后在工程的.pro文件中添加代码“LIBS += -L../ -lmyclass”,在.cpp文件中包含DLL的头文件,然后就可以正常使用DLL了。具体实现代码如下。
#include <QCoreApplication>
#include "myclass.h" //包含DDL的头文件
//#include <QLibrary>
#include <QDebug>
#include <QObject>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);MyClass my(3);qDebug()<<my.getValue();my.setValue(5);qDebug()<<my.getValue();return a.exec();
}
上述程序输出结果为:
![]()
三、存在的一些问题
1)python调用封装了类的DLL可能调用不成功
从DLL的生成可知,c和c++代码生成DLL在代码实现上是不一样的,c++代码需要使用到 extern "C"和“__declspec(dllexport)”。在使用python调用封装了c++类的动态库时,会出现ctypes.CDLL()加载动态库文件不成功的情况,经过测试发现是因为在DLL的函数中使用了new关键字实例化对象造成的,但是具体的原因不清楚。若改用直接申明对象的方式,将对象的指针返回,但是在python中传递该指针后调用函数时会存在访问非法,或访问不到类中变量问题。而同样的DLL文件在QT中调用是完全没有问题的。
2)DLL格式不匹配的问题
在调用DLL时可能存在格式不匹配的问题,这个可能是因为使用的gcc编译器版本不同,或者32位与64位不兼容的原因。应确保DLL库的编译工具与调用它的程序使用相同的gcc,避免兼容性问题。一些比较常用的64位gcc版本可以在这里下载。
四、总结
DLL动态库方便程序模块化开发,但是在进行跨语言调用时,最好只在DLL中封装相应的实现函数,而不要跨语言调用类的实现,避免一些不可预测的问题。
相关文章:
C动态库的生成与在Python和QT中的调用方法
目录 一、动态库生成 1)C语言生成动态库 2)c类生成动态库 二、动态库调用 1)Python调用DLL 2)QT调用DLL 三、存在的一些问题 1)python调用封装了类的DLL可能调用不成功 2)DLL格式不匹配的问题 四、…...
UE求职Demo开发日志#7 强化属性完善
1 实现思路设计 定义一个结构体记录技能树一个单元的信息,命名为FStrengthenCellInfo,一个TArray记录技能树整体信息,需要以下信息: 1.TArray前置技能index 2.FString 描述文本 3.TArray<FMyItemInfo>激活需要的物品ID和…...
Day35:字符串的大小写转换
在 Python 中,字符串的大小写转换是一个常见的操作,它可以帮助我们快速地将字符串中的字母从大写转换为小写,或者从小写转换为大写。Python 提供了多种方法来进行字符串大小写的转换,包括 upper()、lower()、capitalize()、title(…...
喜报丨迪捷软件入选2025年浙江省“重点省专”
根据《浙江省经济和信息化厅 浙江省财政厅关于进一步支持专精特新中小企业高质量发展的通知》(浙经信企业〔2024〕232号)有关要求,经企业自主申报、地方推荐、材料初审以及专家评审等程序,浙江省经济和信息化厅发布了2025年浙江省…...
深度剖析 PyTorch框架:从基础概念到高级应用的深度学习之旅!
目录 一、引言 二、PyTorch 简介 (一)诞生背景与发展历程 (二)核心特点 三、PyTorch 基础概念 (一)张量(Tensor):数据的基石 (二)自动微分&…...
基于C++的DPU医疗领域编程初探
一、大型医院数据处理困境与 DPU 的崛起 在数字化浪潮的席卷下,医疗行业正经历着深刻变革,大型医院作为医疗服务的核心枢纽,积累了海量的数据,涵盖患者的基本信息、诊断记录、检验报告、影像资料等多个维度。这些数据不仅规模庞大,而且增长速度迅猛,传统的中央处理器(C…...
Linux 执行 fdisk -l 出现 GPT PMBR 大小不符 解决方法
目录 前言1. 问题所示2. 原理分析3. 解决方法前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 1. 问题所示 执行fdisk -l的时候出现如下提示: [root@VMS-Centos-test1 ~]# fdisk -l GPT PMBR 大小不符(419430399 != 4294967295),将用写入予以更正…...
图漾相机搭配VisionPro使用简易教程
1.下载并安装VisionPro软件 请自行下载VisonPro软件。 VisionPro 9.0 /9.5/9.6版本经测试,可正常打开图漾相机,建议使用图漾测试过的版本。 2.下载PercipioCameraForVisionPro软件包 使用浏览器下载:https://gitee.com/percipioxyz/camport…...
第一届“启航杯”网络安全挑战赛WP
misc PvzHE 去这个文件夹 有一张图片 QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5} QHCTF For Year 2025 攻防世界有一样的 080714212829302316092230 对应Q 以此类推 QHCTF{FUN} 请找出拍摄地所在位置 柳城 顺丰 forensics win01 这个软件 云沙盒分析一下 md5 ad4…...
大模型训练策略与架构优化实践指南
标题:大模型训练策略与架构优化实践指南 文章信息摘要: 该分析全面探讨了大语言模型训练、架构选择、部署维护等关键环节的优化策略。在训练方面,强调了pre-training、mid-training和post-training的不同定位与目标;在架构选择上…...
新电脑安装系统找不到硬盘原因和解决方法来了
有不少网友反馈新电脑采用官方u盘方式装win10或win100出现找不到硬盘是怎么回事?后来研究半天发现是bios中开启了rst(vmd)模式。如果关闭rst模式肯定是可以安装的,但这会影响硬盘性能,有没有办法解决开启rst模式的情况安装win10或win11呢&…...
【Linux】21.基础IO(3)
文章目录 3. 动态库和静态库3.1 静态库与动态库3.2 静态库的制作和使用原理3.3 动态库的制作和使用原理3.3.1 动态库是怎么被加载的 3.4 关于地址 3. 动态库和静态库 3.1 静态库与动态库 静态库(.a):程序在编译链接的时候把库的代码链接到可…...
深度学习算法:从基础到实践
简介 深度学习作为人工智能领域的一个重要分支,近年来在多个领域取得了显著的成就。本文将从基础概念出发,探讨深度学习算法的核心原理,并介绍一些实际应用案例。 深度学习算法的核心概念 深度学习算法基于人工神经网络,通过构…...
27. 【.NET 8 实战--孢子记账--从单体到微服务】--简易报表--报表服务
报表是每个记账应用所具备的功能,要实现报表功能就需要把账本的核心功能(记账)完成,因此报表服务作为本专栏第一部分单体应用开发中最后一个要实现的功能,这一篇文章很简单,我们一起来实现一个简单的报表服…...
coffee销售数据集分析:基于时间趋势分析的实操练习
**文章说明:**对coffee销售数据集的简单分析练习(时间趋势分析练习),主要是为了强化利用python进行数据分析的实操能力。属于个人的练习文章。 **注:**这是我第一次使用md格式编辑博客文章,排版上还是不是很…...
【转帖】eclipse-24-09版本后,怎么还原原来版本的搜索功能
【1】原贴地址:eclipse - 怎么还原原来版本的搜索功能_eclipse打开类型搜索类功能失效-CSDN博客 https://blog.csdn.net/sinat_32238399/article/details/145113105 【2】原文如下: 更新eclipse-24-09版本后之后,新的搜索功能(CT…...
Centos 修改历史读录( HISTSIZE)
history命令 -c #清空命令历史 -r #读历史文件附加到历史列表 -w #保存历史列表到指定的历史文件 命令历史相关环境变量 HISTSIZE #命令历史记录的条数 HISTFILE #指定历史文件,默认为~/.bash_history HISTFILESIZE #命令历史文件记录历史的条数 以上变量可以 exp…...
lwIP——4 网络接口
1.lwIP网络接口 网络接口(网卡):个人理解是处理网络层和数据传输关系的接口(tcp/ip协议栈中的网络接口层部分),直接与硬件平台打交道 lwIP协议栈支持多种不同的网络接口(网卡)&#…...
pytest自动化测试 - pytest夹具的基本概念
<< 返回目录 1 pytest自动化测试 - pytest夹具的基本概念 夹具可以为测试用例提供资源(测试数据)、执行预置条件、执行后置条件,夹具可以是函数、类或模块,使用pytest.fixture装饰器进行标记。 1.1 夹具的作用范围 夹具的作用范围: …...
FreeRtos的使用教程
定义: RTOS实时操作系统, (Real Time Operating System), 指的是当外界事件发生时, 能够有够快的响应速度,调度一切可利用的资源, 控制实时任务协调一致的运行。 特点: 支持多任务管理, 处理多个事件, 实现更复杂的逻辑。 与计算…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
