Linux C编程:打造一个插件系统
title: ‘Linux C编程:打造一个插件系统’
date: 2017-03-07 21:16:36
tags: linux C
layout: post
comments: true
运行环境:linux
使用语言:c 或者c++
插件,很多人用过,比如游戏插件,编辑器插件这些,
最著名的就数魔兽大脚插件啦,还有vim插件啦,eclipse插件啦,等等
插件有很多种形式,最常见的就是so文件,在windows上就是各种的dll啦
下面就让我们来了解一下插件式编程吧〜〜
举个例子,你开发了一个游戏,一开始只有三个关卡,分享给了你的小伙伴玩
大家玩得很爽,但很快,游戏通关了,还想玩,这时候怎么办呢?
常规做法就是再加两关,然后编译之后,再发给大家,那么问题就来了
每次想加新关卡,都需要重新编译一次,再下载一次,这个流量嘛,1+1.1+1.2+1.3,每次加个0.1,都够你受的_
这个时候嘛,就要引入插件系统了
咱先来写个小程序
//main.c
#include <stdio.h>
#include "game.h" //关于游戏的定义void initGame()
{}
void play()
{printf("我打,我打,我打打打\n");
}
void loadMission()
{}
int main()
{initGame();//初始化游戏 int missionNum=loadMission();//读取关卡数while(1){int missionNo=getchar();//选择关卡missionNo=missionNo-'0';if(missionNo>missionNum){printf("没有此关卡!\n");}play();}}
以上就是一个可扩展的游戏架构,够简单吧〜
下面咱就开始设计这个游戏系统的插件吧
在这里,游戏关卡就是我们的插件,一个插件就是一个关卡
先讲讲一个插件的构造吧
首先是这个关卡的描述,比如名称,难度等
其次就是这个关卡游戏过程了
最后,就是玩关卡的人
按照以上描述,咱定几个结构体吧
//game.h
#include <stdio.h>
#include <string.h>
//游戏玩家描述
typedef struct _player
{int life;//玩家生命
}Player;
//游戏关卡描述
typedef struct _mission
{int level;//关卡难度char missionName[30];//关卡名称void (*process)(Player *);//游戏过程
}Mission;好了,下面就是一个插件的具体内容
```c
//game.c
#include "game.h"
const char name[]="第一关,插件入门";
const int level=1;void firstMission(Player *p)
{printf("oh my god ,somebody hurt me!\n");p->life--;printf("now my life is %d\n",p->life);sleep(1);
}
void gameInfo(Mission *m)
{m->level=level;int len=strlen(name);memcpy(m->missionName,name,len+1);//注意游戏名称不要太长m->process=firstMission;
}
Ok,以上就是一个关卡的所有东西了,虽然看着简单,不过还是建议动手敲敲_
那我们先把这个插件制作出来吧,免得一会忘记了,在终端下执行以下命令:
gcc game.c -fPIC -shared -o firstMission.so -ldl
linux和mac都一样
关卡设计好了,接下来就是怎么样读取我们做好的关卡了
现在实现咱们就loadMission()函数
Mission mission[50];
int loadMission()
{FILE * fp;fp = fopen("missionList.txt", "r");//读取关卡列表文件if (NULL== fp) {return 0;}int ret=0;char namelist[50][50];//最多50个插件,每个插件的名字长度最多50memset(namelist,0,sizeof(namelist));int count=0;while(fgets((char *)&namelist[count], 50, fp)) {ret=strlen(namelist[count]);//计算实际字符串长度if(namelist[count][ret-1]=='\n')namelist[count][ret-1]='\0';//fgets会读多一个换行,所以需要替换掉count++;} fclose(fp);ret=0;//用于累加错误次数for(int i=0;i<count;i++){const char *errmsg;dlerror(); // 清除错误void *m_hLib = (void *)dlopen(namelist[i], RTLD_LAZY);//读取插件if( (errmsg = dlerror()) != NULL ){//printf("err=%s\n",errmsg);打印错误ret++;//累加错误次数continue;}if( m_hLib == NULL ){ret++;//累加错误次数continue;}dlerror(); // 清除错误Info info = (Info)dlsym( m_hLib, "gameInfo" );//提取出插件里面的函数if( (errmsg = dlerror()) != NULL ){dlclose(m_hLib);printf("err=%s\n",errmsg);ret++;continue;}info(&mission[i]);//获取到关卡数据}ret=0;//关卡号//展示下关卡for(int i=0;i<count;i++){if(mission[i].level!=0){printf("%d.%s\n",ret+1,mission[i].missionName);/正式发布的时候就不要啦〜〜ret++;}}count=count-ret;//计算有效关卡数return count;}
好了,上面的代码,不难吧?咱编译一下,就可以跑了
linux下
gcc -o game main.c -Wl,rpath=.
mac下
gcc -o game main.c -Wl,rpath . -dynamic
再准备一个游戏菜单文件,执行
echo firstMission.so >missionlist.txt
好了,再执行
./game
一切顺利的话,你应该能看到自己的关卡列表了〜
接下来干嘛呢?我们现在仅仅是提取出了关卡的名字,还没开始玩游戏呢
以下是改动后的main.c文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include "game.h" //关于游戏的定义Mission mission[50];
void initGame()
{memset(mission,0,sizeof(mission));
}int loadMission()
{FILE * fp;fp = fopen("missionList.txt", "r");//读取关卡列表文件if (NULL== fp) {return 0;}int ret=0;char namelist[50][50];//最多50个插件,每个插件的名字长度最多50memset(namelist,0,sizeof(namelist));int count=0;while(fgets((char *)&namelist[count], 50, fp)) {ret=strlen(namelist[count]);//计算实际字符串长度if(namelist[count][ret-1]=='\n')namelist[count][ret-1]='\0';//fgets会读多一个换行,所以需要替换掉count++;} fclose(fp);ret=0;for(int i=0;i<count;i++){const char *errmsg;dlerror(); // 清除错误void *m_hLib = (void *)dlopen(namelist[i], RTLD_LAZY);if( (errmsg = dlerror()) != NULL ){//printf("err=%s\n",errmsg);打印错误ret++;//累加错误次数continue;}if( m_hLib == NULL ){ret++;//累加错误次数continue;}dlerror(); // 清除错误Info info = (Info)dlsym( m_hLib, "gameInfo" );if( (errmsg = dlerror()) != NULL ){dlclose(m_hLib);printf("err=%s\n",errmsg);ret++;continue;}info(&mission[i]);}//展示下关卡for(int i=0;i<count;i++){if(mission[i].level!=0){printf("%d.%s\n",i+1,mission[i].missionName);//正式发布的时候就不要啦〜〜}}count=count-ret;//计算有效关卡数return count;}
int main()
{initGame();//初始化游戏 int missionNum=loadMission();//读取关卡数if(missionNum==0){printf("游戏异常退出\n");return -1;}//初始化一个角色,并满血Player p;while(1){p.life=100;printf("请选择关卡\n");for(int i=0;i<missionNum;i++){printf("%d.%s\n",i+1,mission[i].missionName);}int missionNo=getchar();//选择关卡missionNo=missionNo-'0';if(missionNo>missionNum || missionNo<1){printf("没有此关卡!\n");continue;}//读取来的关卡肯定是有难度等级的,没有就是无效关卡if(mission[missionNo-1].level!=0){while(p.life>0)mission[missionNo-1].process(&p);}printf("Game Over!\n\n\n");}}
这就是一个完整的游戏啦,感兴趣的同学可以继续扩展哟〜〜后面就是不断得出扩展啦
你问我怎么扩展?
好吧,自己把game.c里面的内容改改,然后编译出来,换个名字,然后在missionlist.txt里面加一行,就ok了
还不懂?那你只能给我打赏了_
相关文章:
Linux C编程:打造一个插件系统
title: ‘Linux C编程:打造一个插件系统’ date: 2017-03-07 21:16:36 tags: linux C layout: post comments: true 运行环境:linux 使用语言:c 或者c 插件,很多人用过,比如游戏插件,编辑器插件这些, 最著…...
基于毫米波生物感知雷达+STM32设计的独居老人居家监护系统(微信小程序)(192)
基于毫米波生物感知雷达设计的独居老人居家监护系统(微信小程序)(192) 文章目录 一、前言1.1 项目介绍【1】项目功能介绍【2】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】60G毫米波生物感知雷达原理【3】ESP8266模块配置【4】供电方式1.3 项目开发背景【1】选题的意义…...
C++——类和对象(下)
目录 一、再探构造函数 1.基本定义以及用法 2.必须在初始化列表初始化的成员变量 3.成员变量声明位置的缺省值(C11) 4.成员变量初始化顺序 二、隐式类型转换 三、static成员 四、友元 五、内部类 六、匿名对象 七、日期类实现 一、再探构造函数…...
Android中集成前端页面探索(Capacitor 或 Cordova 插件)待完善......
探索目标:Android中集成前端页面 之前使用的webview加载html页面,使用bridge的方式进行原生安卓和html页面的通信的方式,探索capacitor-android插件是如何操作的 capacitor-android用途 Capacitor 是一个用于构建现代跨平台应用程序的开源框…...
玩转CSS:用ul li +JS 模拟select,避坑浏览器不兼容。
玩转CSS:用ul li JS 模拟select,避坑浏览器不兼容。 在前端的工作中,经常会遇到 selcet控件,但我们用css来写它的样式时候,总是不那么令人满意,各种浏览器不兼容啊有没有? 那么,我…...
介绍下PolarDB
业务中用的是阿里云自研的PolarDB,分析下PolarDB的架构。 认识PolarDB 介绍 PolarDB是阿里云自研的,兼容MySQL、PostageSQL以及支持MPP的PolarDB-X的高可用、高扩展性的数据库。 架构 部署 云起实验室 - 阿里云开发者社区 - 阿里云 (aliyun.com) 数…...
基于微信小程序+SpringBoot+Vue的儿童预防接种预约系统(带1w+文档)
基于微信小程序SpringBootVue的儿童预防接种预约系统(带1w文档) 基于微信小程序SpringBootVue的儿童预防接种预约系统(带1w文档) 开发合适的儿童预防接种预约微信小程序,可以方便管理人员对儿童预防接种预约微信小程序的管理,提高信息管理工作效率及查询…...
go语言day15 goroutine
Golang-100-Days/Day16-20(Go语言基础进阶)/day17_Go语言并发Goroutine.md at master rubyhan1314/Golang-100-Days GitHub 第2讲-调度器的由来和分析_哔哩哔哩_bilibili 一个进程最多可以创建多少个线程?-CSDN博客 引入协程 go语言中内置了协程goroutine&#…...
Mindspore框架循环神经网络RNN模型实现情感分类|(六)模型加载和推理(情感分类模型资源下载)
Mindspore框架循环神经网络RNN模型实现情感分类 Mindspore框架循环神经网络RNN模型实现情感分类|(一)IMDB影评数据集准备 Mindspore框架循环神经网络RNN模型实现情感分类|(二)预训练词向量 Mindspore框架循环神经网络RNN模型实现…...
System类
System类常见方法 ① exit 退出当前程序 public static void main(String[] args) {System.out.println("ok1");//0表示状态,即正常退出System.exit(0);System.out.println("ok2");} ② arraycopy 复制数组元素 复制的数组元素个数必须<原数…...
【前端 02】新浪新闻项目-初步使用CSS来排版
在今天的博文中,我们将围绕“新浪新闻”项目,深入探讨HTML和CSS在网页制作中的基础应用。通过具体实例,我们将学习如何设置图片、标题、超链接以及文本排版,同时了解CSS的引入方式和选择器优先级,以及视频和音频标签的…...
HarmonyOS和OpenHarmony区别联系
前言 相信我们在刚开始接触鸿蒙开发的时候经常看到HarmonyOS和OpenHarmony频繁的出现在文章和文档之中,那么这两个名词分别是什么意思,他们之间又有什么联系呢?本文将通过现有的文章和网站内容并与Google的AOSP和Android做对比,带…...
llama模型,nano
目录 llama模型 Llama模型性能评测 nano模型是什么 Gemini Nano模型 参数量 MMLU、GPQA、HumanEval 1. MMLU(Massive Multi-task Language Understanding) 2. GPQA(Grade School Physics Question Answering) 3. HumanEval llama模型 Large Language Model AI Ll…...
ElasticSearch的应用场景和优势
ElasticSearch是一个开源的分布式搜索和分析引擎,它以其高性能、可扩展性和实时性在多个领域得到了广泛应用。以下是ElasticSearch的主要应用场景和优势: 应用场景 实时搜索: ElasticSearch以其快速、可扩展和实时的特性,成为实…...
git 、shell脚本
git 文件版本控制 安装git yum -y install git 创建仓库 将文件提交到暂存 git add . #将暂存区域的文件提交仓库 git commit -m "说明" #推送到远程仓库 git push #获取远程仓库的更新 git pull #克隆远程仓库 git clone #分支,提高代码的灵活性 #检查分…...
阿里云服务器 篇六:GitHub镜像网站
文章目录 系列文章搭建镜像网站的2种方式使用 Web 抓取工具 (Spider 技术)使用 Web 代理服务器使用 nginx 搭建GitHub镜像网站基础环境搭建添加对 github.com 的转发配置添加对 raw.githubusercontent.com 的转发配置配置更改注意事项(可选)缓存优化为新增设的二级域名配置DN…...
强化学习学习(三)收敛性证明与DDPG
文章目录 证明收敛? Deep RL with Q-FunctionsDouble Q-Learning理论上的解法实际上的解法 DDPG: Q-Learning with continuous actionsAdvanced tips for Q-Learning 证明收敛? 对于Value迭代:不动点证明的思路 首先定义一个算子 B : B V ma…...
培养前端工程化思维,不要让一行代码毁了整个程序
看《阿丽亚娜 5 号(Ariane 5)火箭爆炸》有感。 1、动手写项目之前,先进行全局性代码逻辑思考,将该做的事情,一些细节,统一建立标准,避免为以后埋雷。 2、避免使用不必要或无意义的代码、注释。…...
电子文件怎么盖章?
电子文件怎么盖章?电子文件盖章是数字化办公中常见的操作,包括盖电子公章和电子骑缝章。以下是针对这两种情况的详细步骤: 一、盖电子公章 方法一:使用专业软件 选择软件:选择一款专业的电子签名或PDF编辑软件&…...
IDEA在编译的时候报Error: java: 找不到符号符号: 变量 log lombok失效问题
错误描述 idea因为lombok的报错: java: You arent using a compiler supported by lombok, so lombok will not work and has been disabled.Your processor is: com.sun.proxy.$Proxy8Lombok supports: sun/apple javac 1.6, ECJ 原因:这是由于Lombok的版本过低的…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
