跳到主要内容

创建插件工程

开发环境要求

工具版本要求
Visual Studio2019 或更高
C++ 标准C++14
编译器MSVC (v142+)
依赖库OpenCV 3.4.1(可选)

快速开始

1. 创建项目结构

mkdir Plugin.MyPlugin
cd Plugin.MyPlugin
mkdir Tools
mkdir Include

2. 引用 ToolBase 头文件

从 ToolBank 工程中复制以下文件到项目:

MainUI.Plugin.ToolBase/Base/
├── ToolBaseNative.h # 插件基类
├── ToolFactory.h # 注册工厂
├── Macro.h # 宏定义和类型
├── Variable.h # 变量基类
├── DataType.h # 数据类型定义
├── ProjectControl.h # 项目控制器
├── ProjectArgument.h # 参数定义
├── ProjectVariables.h # 变量池
└── Variable/
├── Image.h
├── Point2D.h
├── Point3D.h
├── Line2D.h
├── Rectangle2D.h
├── Circle2D.h
├── Polygon2D.h
└── Region.h

3. 创建算子类

每个算子需要继承 ToolBaseNative 类。

头文件示例

// Tools/MyFilter.h
#pragma once
#include <ToolBaseNative.h>

namespace DLJ
{
namespace VT
{

class MyFilter : public ToolBaseNative
{
public:
MyFilter();

#pragma region DoNotChange
public:
// 工厂创建函数
static ToolBaseNative* Create() { return new MyFilter; }

// 返回算子名称
const std::string& GetName() const { return Name; }

// 返回算子分类
const ToolCategory GetCategory() const { return ToolCategory::Image; }

// 实现算子逻辑
ECode Apply(ProjectControl& ctx) override;

ECode parseInputVariable();
ECode setOutputVariable();

protected:
static const string Name;
#pragma endregion

public:
// 自定义实现
ECode do_Filter();

private:
// 输入变量
DLJ_IN_V(Image) m_InputImage; // 单值输入
DLJ_IN_V(double) m_KernelSize; // 单值输入
DLJ_IN_V(int) m_Iterations; // 列表输入

// 输出变量
DLJ_OUT_S(Image) m_OutputImage; // 单值输出
};

} // namespace VT
} // namespace DLJ

源文件示例

// Tools/MyFilter.cpp
#include "MyFilter.h"

namespace DLJ
{
namespace VT
{

// 注册算子:名称 -> 创建函数
const std::string MyFilter::Name = ToolFactory::Register(
"MyFilter", // 算子显示名
MyFilter::Create // 创建函数指针
);

// 构造函数:定义输入输出
MyFilter::MyFilter()
{
// 输入参数
setupInput("InputImage", IMAGE, "InputImage", "",
&m_InputImage, VAR_MODE::ALLOW_SINGLE,
u8"输入图像");

setupInput("KernelSize", DOUBLE, "3.0", "",
&m_KernelSize, VAR_MODE::ALLOW_EMPTY,
u8"卷积核大小");

setupInput("Iterations", INTEGER, "1", "",
&m_Iterations, VAR_MODE::ALLOW_MANY,
u8"迭代次数,支持列表");

// 输出参数
setupOutput("OutputImage", IMAGE, "OutputImage",
&m_OutputImage, u8"滤波后图像");

// 完成设置
SetupDone();
}

// Apply 函数:执行流程
ECode MyFilter::Apply(ProjectControl& ctx)
{
// 1. 解析输入
auto err = parseInputVariable();
if (err != ECode::ALL_OK) return err;

// 2. 执行算法
err = do_Filter();
if (err != ECode::ALL_OK) return err;

// 3. 输出结果
err = setOutputVariable();
if (err != ECode::ALL_OK) return err;

return err;
}

// 解析输入
ECode MyFilter::parseInputVariable()
{
auto err = ParseInputs();
if (err == ECode::ALL_OK)
{
// 自定义参数校验
if (m_KernelSize.empty())
{
SET_ERROR("KernelSize 不能为空");
return ECode::LOGIC_ERROR;
}
}
return err;
}

// 设置输出
ECode MyFilter::setOutputVariable()
{
return Outputs();
}

// 实际算法实现
ECode MyFilter::do_Filter()
{
// 获取输入
cv::Mat src = m_InputImage[0].m_Image;
double kernel = m_KernelSize[0];

// 执行滤波(示例)
cv::Mat dst;
cv::GaussianBlur(src, dst, cv::Size(0, 0), kernel);

// 设置输出
m_OutputImage = Image(dst);

return ECode::ALL_OK;
}

} // namespace VT
} // namespace DLJ

4. 配置 DLL 导出

在项目属性中:

  1. C/C++ → 预处理器:添加 DLJ_TOOLSTOOL_PLUGIN
  2. 链接器 → 输入:确保以下库
    • ToolBaseNative.lib
    • ToolFactory.lib
    • opencv_world341.lib(可选)
  3. C/C++ → 代码生成:运行库设置为 /MD/MDd

5. 实现 DLL 导出

在项目中创建一个导出文件,确保所有算子可被加载:

// Tools/Export.cpp
#define DLJ_TOOLS
#include <ToolFactory.h>

extern "C" {

__declspec(dllexport) int RegisterAllTools()
{
// 注册所有算子(通过静态构造自动注册)
return 0;
}

__declspec(dllexport) int DeregisterAllTools()
{
ToolFactory::ClearAll();
return 0;
}

__declspec(dllexport) const char** GetAllToolsNames(int* toolsCount)
{
auto names = ToolFactory::GetFactoryNames();
*toolsCount = (int)names.size();

static std::vector<const char*> result;
result.clear();
for (auto& name : names)
result.push_back(name.c_str());

return result.data();
}

} // extern "C"

算子分类

使用 ToolCategory 枚举指定算子分类:

分类枚举值说明
图像处理ToolCategory::Image滤波、变换、形态学等
区域操作ToolCategory::RegionROI 处理、轮廓分析等
数学运算ToolCategory::Math数值计算、表达式等
变量定义ToolCategory::Variable定义变量/常量
控制流ToolCategory::ControlFlowIF/ELSE/LOOP 等
文件读写ToolCategory::FileIO文件/数据库操作
自定义ToolCategory::CustomTools用户自定义分类

输入输出模式

VAR_MODE 定义

enum VAR_MODE
{
ALLOW_EMPTY = 0, // 允许空值/单值/列表
ALLOW_SINGLE, // 仅允许单值
ALLOW_MANY, // 允许单值或列表
OUT_IS_EMPTY // 输出空值模式
};

变量类型宏

// 输入变量
DLJ_IN_V(T) // 输入,向量类型
DLJ_IN_S(T) // 输入,单值类型

// 输出变量
DLJ_OUT_V(T) // 输出,向量类型
DLJ_OUT_S(T) // 输出,单值类型

构建与测试

编译

# Release x64 模式
MSBuild Plugin.MyPlugin.sln /p:Configuration=Release /p:Platform=x64

本地测试

  1. 将编译生成的 DLL 复制到 ToolBank 插件目录
  2. 启动 ToolBank
  3. 在"插件管理"中确认插件已加载
  4. 在程序编辑器中添加算子并测试

调试技巧

查看算子信息

// 在构造函数中添加调试日志
DLJ_PUSH_CALLSTACK("MyFilter 构造函数被调用");

参数验证

// 使用宏验证输入
DLJ_ASSERT_VECTOR_SIZE(m_InputImage, >, 0); // 至少一个图像
DLJ_ASSERT_vA_OPTR_vB(m_KernelSize, >=, 1.0); // 核大小 >= 1.0

运行时错误

SET_ERROR("自定义错误信息");
return ECode::LOGIC_ERROR;

常见问题

问题解决方案
算子无法注册检查 ToolFactory::Register 是否在静态初始化时调用
DLL 加载失败检查依赖库是否都在可执行目录中
输入参数为空检查 VAR_MODE 设置和 ParseInputs() 调用
输出变量为空确保 Outputs()Apply 中被调用

参考示例

可参考 ToolBank 工程中的现有插件实现:

  • Plugin.CV - 图像处理类插件
  • Plugin.DL - 深度学习类插件
  • Plugin.Finance - 金融数据处理插件