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中封装相应的实现函数,而不要跨语言调用类的实现,避免一些不可预测的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/9938.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET MAUI进行UDP通信(二)

上篇文章有写过一个简单的demo&#xff0c;本次对项目进行进一步的扩展&#xff0c;添加tabbar功能。 1.修改AppShell.xaml文件&#xff0c;如下所示&#xff1a; <?xml version"1.0" encoding"UTF-8" ?> <Shellx:Class"mauiDemo.AppShel…

什么是Maxscript?为什么要学习Maxscript?

MAXScript是Autodesk 3ds Max的内置脚本语言,它是一种与3dsMax对话并使3dsMax执行某些操作的编程语言。它是一种脚本语言,这意味着您不需要编译代码即可运行。通过使用一系列基于文本的命令而不是使用UI操作,您可以完成许多使用UI操作无法完成的任务。 Maxscript是一种专有…

适配器模式

目录 一、概念 1、定义 2、涉及到的角色 二、类适配器 1、类图 2、代码示例 &#xff08;1&#xff09;水饺&#xff08;源角色&#xff09; &#xff08;2&#xff09;烹饪&#xff08;目的角色&#xff09; &#xff08;3&#xff09;食品适配器&#xff08;适配器角…

YOLO11/ultralytics:环境搭建

前言 人工智能物体识别行业应该已经饱和了吧&#xff1f;或许现在并不是一个好的入行时候。 最近看到了各种各样相关的扩展应用&#xff0c;为了理解它&#xff0c;我不得不去尝试了解一下。 我选择了git里非常受欢迎的yolo系列&#xff0c;并尝试了最新版本YOLO11或者叫它ultr…

SQL注入漏洞之绕过[前端 服务端 waf]限制 以及 防御手法 一篇文章给你搞定

目录 绕过手法 前端代码绕过 后端代码绕过 各种字段进行验证 union 大小写绕过 双写逃过 强制类型判断 引号特殊编码处理。 内联注释绕过 注释符绕过 or/and绕过 空格绕过 防御SQL注入的方法 使用预编译语句 使用存储过程 检查数据类型 绕过手法 前端代码绕过…

使用冒泡排序模拟实现qsort函数

1.冒泡排序 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h>int main() {int arr[] { 0,2,5,3,4,8,9,7,6,1 };int sz sizeof(arr) / sizeof(arr[0]);//冒泡排序一共排序 sz-1 趟for (int i 0; i < sz - 1; i){//标志位&#xff0c;如果有序&#xff0c;直接…

【Linux】线程互斥与同步

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…

【数据结构】二叉树

二叉树 1. 树型结构&#xff08;了解&#xff09;1.1 概念1.2 概念&#xff08;重要&#xff09;1.3 树的表示形式&#xff08;了解&#xff09;1.4 树的应用 2. 二叉树&#xff08;重点&#xff09;2.1 概念2.2 两种特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储2.5 二叉树的…

1.五子棋对弈python解法——2024年省赛蓝桥杯真题

问题描述 原题传送门&#xff1a;1.五子棋对弈 - 蓝桥云课 "在五子棋的对弈中&#xff0c;友谊的小船说翻就翻&#xff1f;" 不&#xff01;对小蓝和小桥来说&#xff0c;五子棋不仅是棋盘上的较量&#xff0c;更是心与心之间的沟通。这两位挚友秉承着"友谊第…

Origami Agents:AI驱动的销售研究工具,助力B2B销售团队高效增长

在竞争激烈的B2B市场中,销售团队面临着巨大的挑战——如何高效地发现潜在客户并进行精准的外展活动。Origami Agents通过其创新的AI驱动研究工具,正在彻底改变这一过程。本文将深入探讨Origami Agents的产品特性、技术架构及其快速增长背后的成功因素。 一、一句话定位 Ori…

Java---猜数字游戏

本篇文章所实现的是Java经典的猜数字游戏 , 运用简单代码来实现基本功能 目录 一.题目要求 二.游戏准备 三.代码实现 一.题目要求 随机生成一个1-100之间的整数(可以自己设置区间&#xff09;&#xff0c;提示用户猜测&#xff0c;猜大提示"猜大了"&#xff0c;…

NLP深度学习 DAY5:Seq2Seq 模型详解

Seq2Seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种用于处理输入和输出均为序列任务的深度学习模型。它最初被设计用于机器翻译&#xff0c;但后来广泛应用于其他任务&#xff0c;如文本摘要、对话系统、语音识别、问答系统等。 核心思想 Seq2Seq 模型的目标是将…

数据结构 队列

目录 前言 一&#xff0c;队列的基本知识 二&#xff0c;用数组实现队列 三&#xff0c;用链表实现队列 总结 前言 接下来我们将学习队列的知识&#xff0c;这会让我们了解队列的基本概念和基本的功能 一&#xff0c;队列的基本知识 (Queue) 我们先来研究队列的ADT&#xff0c…

Git 版本控制:基础介绍与常用操作

目录 Git 的基本概念 Git 安装与配置 Git 常用命令与操作 1. 初始化本地仓库 2. 版本控制工作流程 3. 分支管理 4. 解决冲突 5. 回退和撤销 6. 查看提交日志 前言 在软件开发过程中&#xff0c;开发者常常需要在现有程序的基础上进行修改和扩展。但如果不加以管理&am…

Java 大视界 -- Java 大数据在量子通信安全中的应用探索(69)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

国产碳化硅(SiC)MOSFET模块在电镀电源中全面取代进口IGBT模块

国产碳化硅&#xff08;SiC&#xff09;MOSFET模块在电镀电源中全面取代进口IGBT模块&#xff0c;倾佳电子杨茜分析以下几方面的技术、经济和政策优势&#xff1a; 倾佳电子杨茜致力于推动SiC碳化硅模块在电力电子应用中全面取代IGBT模块&#xff0c;助力电力电子行业自主可控…

linux用户管理

创建用户&#xff1a;useradd &#xff08;创建用户命令的详细使用&#xff1a;如何创建用户-CSDN博客&#xff09; &#xff08;如何创建具有重复uid的用户&#xff1a;如何创建具有重复uid的用户-CSDN博客&#xff09; 删除用户&#xff1a;userdel &#xff08;删除用户命…

【C++动态规划 离散化】1626. 无矛盾的最佳球队|2027

本文涉及知识点 C动态规划 离散化 LeetCode1626. 无矛盾的最佳球队 假设你是球队的经理。对于即将到来的锦标赛&#xff0c;你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。 然而&#xff0c;球队中的矛盾会限制球员的发挥&#xff0c;所以必须选…

【安全测试】测开方向学习遇到的问题记录

【问题一】springboot如何访问静态资源文件 springboot启动根路径位置 F:\untitled05\demo4\src\main\resources\static 例如图片位置存放在F:\untitled05\demo4\src\main\resources\static即可 配置文件配置 spring.web.resources.static-locationsfile:/F:/untitled05/de…

Github 2025-01-25Rust开源项目日报Top10

根据Github Trendings的统计,今日(2025-01-25统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Python项目1Vue项目1JavaScript项目1Deno: 现代JavaScript和TypeScript运行时 创建周期:2118 天开发语言:Rust, JavaScript协议类型…