C++ 源码库
[🕒 预计 15 分钟] | 难度:入门
别人用 C++ 写好的函数(.h / .cpp 源码文件),不需要先编译成 DLL,直接把源码放进项目、声明成中文命令就能调用——源码会和你的工程一起编译,补全、参数提示、类型检查全部自动生效。
1. 三种 C++ 接入方式怎么选
| 方式 | 适合场景 | 前提 |
|---|---|---|
| C++ 源码库(本页) | 拿得到源码,允许随项目一起分发 | 只要 .h/.cpp 文件 |
| DLL 命令声明 | 只有编译好的 .dll,拿不到源码 | 先编译出 DLL |
| .lbmod 模块 | 跨项目复用、隐藏源码、分发给别人 | 模块封装流程 |
2. 把源码放进项目
- 在 解决方案资源管理器 中右键项目节点,选择 添加 C++ 源码…。
- 在文件对话框中选中别人给你的
.cpp/.h文件(可多选)。 - 文件会被复制到项目目录的
cpp/文件夹下(重名自动加-2、-3后缀),并自动打开「C++ 源码库」声明文件。
也可以用命令面板执行 项目:添加 C++ 源码…,或手动把源码文件放进项目源码目录。
3. 声明中文命令
在声明文件 项目C++源码库.lcpp 中(项目节点的「C++ 源码库」按钮可随时打开),按下面的格式声明:
包 项目C++源码库
C++源码库 数学库
源码 = cpp/mymath.cpp
头文件 = cpp/mymath.h
整数型 加法计算(整数型 a, 整数型 b) = add
备注: 计算两数之和
小数型 平均值(小数型 总和, 整数型 个数) = average
结束C++源码库源码 =:参与编译的.cpp文件(相对项目源码目录),必填,可写多行。头文件 =:可选。写了就以你的头文件里的声明为准;不写则 IDE 按「类型映射表」自动生成期望签名。= add:源码里的 C++ 函数名(英文),必须填写;左边的中文命令名由你起。
声明完成后,在窗口代码里直接调用:
局部 整数型 和值 = 加法计算(123, 456)4. C++ 侧要怎么写
C++ 函数必须是全局自由函数,签名与声明一致:
| 中文类型 | C++ 参数写法 | C++ 返回写法 |
|---|---|---|
| 整数型 | int | int |
| 长整数型 | long long | long long |
| 小数型 / 单精度小数型 | double / float | 同左 |
| 逻辑型 | bool | bool |
| 字节型 | unsigned char | 同左 |
| 文本型 | const wchar_t*(或 std::wstring 值传递) | const wchar_t* |
| 字节集 | const std::vector<unsigned char>& | 按值 std::vector<unsigned char> |
| 指针整数 | uintptr_t | uintptr_t |
| 传址参数 | 指针,如 int*(调用端自动传 &变量) | — |
// cpp/mymath.cpp
#include "mymath.h"
int add(int a, int b) {
return a + b;
}
const wchar_t* greet(const wchar_t* name) {
static std::wstring message;
message = std::wstring(L"你好,") + (name ? name : L"");
return message.c_str();
}5. 传函数(回调)
命令参数可以声明处理器并带内联签名,把中文子程序直接传给 C++:
空 执行进度(整数型 次数, 处理器 进度回调(整数型 序号, 文本型 阶段)) = run_progressC++ 侧形参写 std::function<void(int, const wchar_t*)>(回调返回固定为空):
void run_progress(int count, std::function<void(int, const wchar_t*)> callback) {
for (int i = 1; i <= count; ++i) callback(i, L"步");
}调用时传 &子程序名(子程序写在窗口类里,签名必须与内联签名一致,IDE 会强校验):
回调计数 = 0
执行进度(5, &进度回调)注意:默认情况下回调在与调用相同的线程里直接执行(线程透传),不要在回调外长期保存它。
5.1 跨线程封送(界面线程)
C++ 侧要在工作线程里触发回调(后台下载进度、线程池任务等)时,给处理器参数加 界面线程 后缀:
空 执行线程任务(整数型 次数, 处理器 线程进度(整数型 序号, 文本型 阶段) 界面线程) = run_worker这样回调被工作线程触发时,参数会以值拷贝快照经 PostMessage 投递到界面线程执行——处理器里可以放心操作控件。语义要点:
- 必须显式写
界面线程才封送,不写就维持线程透传(封送把同步调用变成了异步投递,不允许悄悄发生); - 封送回调不能带
回传 类型(异步拿不回返回值,两者同写会在声明时报错); - 同一线程的多次投递按顺序执行,跨线程不保证顺序;
- 处理器里不要阻塞,投递方也不要等待——封送是「发了就走」(fire-and-forget)。
6. 类(句柄化)
用类块把 C++ 类包装成「创建 / 销毁 / 方法」命令,句柄是长整数型:
C++源码库 计数器库
头文件 = cpp/counter.h
类 计数器 = Counter
方法 计数器 创建(整数型 初始值)
方法 空 销毁()
方法 整数型 取当前() = get_value
方法 空 累加(整数型 步长) = add_value
结束类
结束C++源码库调用:
局部 长整数型 对象 = 0
局部 整数型 当前值 = 0
对象 = 计数器_创建(40)
计数器_累加(对象, 2)
当前值 = 计数器_取当前(对象)
计数器_销毁(对象)要点:类定义必须来自同库声明的「头文件 =」(可以全部内联在头文件里);「创建」「销毁」是保留名(分别生成 new / delete);句柄变量可以直接用类名声明(局部 计数器 对象 = 0),也可以写 长整数型;句柄是裸指针,复制句柄等于共享对象,用完必须 销毁;多步句柄流程要先声明(不带初始值)再按序赋值——带初始值的局部声明会被提升到子程序最前,导致后面的初始化器抢在中间步骤之前执行。
7. 进阶能力(v3)
回调返回值:处理器 校验器(整数型 值) 回传 逻辑型 —— C++ 侧收 std::function<bool(int)>,中文子程序返回逻辑型即可(缺省返回为空)。
一维数组:整数型[] 求和(整数型[] 数据) —— C++ 侧参数写 const std::vector<int>&、返回按值 std::vector<int>;文本型数组的元素是 std::wstring。数组返回值建议就地嵌套消费(如 校验缩放(缩放数组(源数组(), 3)))。
附加包含目录:包含目录 = cpp/third_party —— 整个目录会随源码一起复制,.cpp 里写相对路径 #include "third_party/xxx.h" 即可命中。
异常捕获:库内写一行 异常 = 捕获 —— 本库全部 C++ 函数经 try/catch 包装,抛异常不再让程序崩溃,而是返回零值;用自动生成的 库名_取错误() 读取异常文本(读取后清空,没有异常时为空文本)。
8. 命名空间
C++ 函数在命名空间里?库内写一行 命名空间 = xxx(整个库的函数必须在同一命名空间):
C++源码库 扩展库
源码 = cpp/ext.cpp
命名空间 = lbv4
整数型 三数相加(整数型 a, 整数型 b, 整数型 c) = plus3
结束C++源码库.lcpp 调用写法完全不变(IDE 自动生成全局转发函数)。注意:只作用于函数命令;类块不支持命名空间(类定义来自你的头文件)。
9. 结构体(把 C++ 结构体当数据包传)
库内用结构体块声明一个结构体,字段逐行写(// 备注 可选):
C++源码库 几何库
源码 = cpp/geometry.cpp
头文件 = cpp/geometry.h
结构体 点 = Point
小数型 x // 横坐标
小数型 y
文本型 名称
结束结构体
小数型 两点距离(点 a, 点 b) = distance
点 取中点(点 a, 点 b) = midpoint
结束C++源码库IDE 会自动合成一整套命令:点_创建()(造一个全零的点并返回句柄)、点_销毁(句柄),以及每个字段的 点_取X(句柄) / 点_置X(句柄, 值)。命令的参数和返回都可以直接写结构体名。
C++ 侧怎么写:
- 参数写
const Point&(IDE 生成的期望签名就是这个形态;写按值Point是另一个函数签名,会链接失败); - 返回按值写
Point(中文侧拿到的是自动包好的句柄,用完要点_销毁); - 文本型字段就是
std::wstring——和 DLL 结构体不同,这里不需要定长数组,直接写普通结构体即可。
// cpp/geometry.h
#pragma once
#include <string>
struct Point {
double x;
double y;
std::wstring 名称;
};
double distance(const Point& a, const Point& b);
Point midpoint(const Point& a, const Point& b);中文侧调用(句柄流程记住「先声明、再按序赋值」):
局部 点 a = 0
局部 点 b = 0
局部 点 中点 = 0
a = 点_创建()
b = 点_创建()
点_置x(a, 3)
点_置y(a, 4)
中点 = 取中点(a, b)
调试输出(点_取x(中点))
点_销毁(中点)
点_销毁(b)
点_销毁(a)结构体定义放哪? 库写了「头文件 =」就以你头文件里的 struct 为准(字段行只负责生成取/置命令);不写头文件时 IDE 会按字段行直接生成 struct 定义,你的 .cpp 里写 #include "CppSourceLibraries.h" 就能拿到它。
边界:结构体只在本库内可用;字段不支持数组、嵌套结构体和字节集;不支持与命名空间同库使用;类方法的参数/返回暂不支持结构体(用普通函数命令传)。
10. 注意事项(红线)
- 只支持普通全局函数:模板、重载、类成员函数暂不支持(声明时会给出中文提示)。
- 源码文件要保存为 UTF-8 编码(否则构建时中文注释会导致报错)。
- 源码里不要定义
main、wWinMain、DllMain等入口函数。 - 函数内不要抛 C++ 异常。
- 要隐藏源码或分发给别的项目复用时,请改用 DLL 命令声明或模块封装。