1. 实现的效果
没有使用外部导入时,
外部功能数据库如下:
id | name | rule | notes |
---|---|---|---|
1 | 外部规则1 | ( 3 * x + 2 * y ) / 5 | 加权平均 |
2 | 外部规则2 | sqrt( x * x + y * y ) | 平方和 |
导入到下拉菜单
2. 导入的功能数据库的代码
//导入功能数据库按钮
void Widget::on_pushButton_2_clicked()
{
//ui->comboBox->addItem("外部功能1");
//ui->comboBox->addItem("外部功能2");
//读取外部规则表,并写入下拉菜单name
QSqlQuery query(db);
QString sql=QString("select * from rules;");
query.exec(sql);
while(query.next())
{
//把 rule 表中的 name 载入到下拉框
QString rule_name=QString("%1").arg(query.value("name").toString());
ui->comboBox->addItem(rule_name);
}
}
3. 实现外部功能的办法
1. 根据表单自动生成代码。格式如下:
//注释:[notes]
float rules_[id](float x,float y){return [rule];}
生成的完整 rule.c 代码如下:
/****************************************/
//编译此代码为 rules .dll,然后复制.exe目录下,以更新功能
//更新时间:2020年-03月-24日 18时-47分-26秒
/****************************************/
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#include <math.h>
/****************************************/
//函数名:外部功能1
//注释:加权平均
/****************************************/
float DLL_EXPORT rule_1(float x,float y){return (3*x+2*y)/5;}
/****************************************/
//函数名:外部功能2
//注释:平方和
/****************************************/
float DLL_EXPORT rule_2(float x,float y){return sqrt(x*x+y*y);}
2. rule.c 编译成为动态链接库。
编写批处理脚本,实现自动代码编译。
echo 正在执行 rule.c 的编译....
cd [rule.c文件所在路径]
echo 转到当前目录
gcc -shared -o rule.dll rule.c
echo 编译 rule.c 为 dll 文件...
echo 执行完毕...
新建记事本,写入此脚本,命名为 自动编译.bat。
于是,双击这个文件,即可实现自动编译,得到外部功能表的动态链接库。
也可以从QT程序中调用此脚本,实现自动编译。代码如下:
//规则代码编译成动态链接库
void Widget::on_pushButton_2_clicked()
{
qDebug("规则代码编译成动态链接库");
//调用外部脚本,编译代码
QProcess p(NULL);
p.setWorkingDirectory("C:/Users/22672/Desktop");
QString command = "C:/Users/22672/Desktop/自动编译.bat";
p.start(command);
p.waitForFinished();
qDebug("规则代码编译成功!");
}
3. 根据下拉选项,得到外部功能的 name,查询 rules 数据库,得到 id,然后构造函数名字为 rule_[id],显示加载动态链接库。进行计算,得到结果。
代码如下:
//则查找规则名称 name,构造函数名 rule_id
QString sql=QString("select * from rules where name='%1';").arg(item);
QSqlQuery query(db);
query.exec(sql);
query.next();
QString str_temp = QString("rule_%1").arg(query.value("id").toInt());
// outside_rule_function 要转换为 char* 否则 resolve 不认
QByteArray str_temp2 = str_temp.toUtf8();
char* outside_rule_function = str_temp2.data();
//加载链接库 rules.dll
QLibrary lib("rule.dll");//rules.dll 放在 xxx.exe文件夹下
if(lib.load()==true)
{
typedef float(*rule_function)(float x,float y);//定义函数
if(query.value("id").toInt()!=0)//查找成功时
{
rule_function outside_rule=(rule_function)lib.resolve(outside_rule_function);
ans = outside_rule(x,y);
}
总结:
- 外部功能数据库。增、删、改、查,自动生成对应的代码,自动调用批处理脚本编译此代码,得到动态链接库。
- 主程序。根据外部功能数据库,查表加载下拉选项。
- 主程序。根据下拉选项,查表构造函数名,动态加载动态链接库,运行指定的功能。
- 关键技术:dll 动态加载; 外部功能数据库;批处理编译程序
- 整个架构如下。