YStudio Y++

Y++ 指针 / DLL 边界对照手册

Y++ / YStudio 开发文档 · 一点滴

本文整理 整数指针、文本指针、字节集指针 以及相关 DLL / WinAPI 边界在 Y++ 中的全部处理方式:已支持、半支持、不支持,以及推荐写法。

相关入口:


1. 三层机制(先选对层)

用途 典型命令 / 语法
A. .yp 自动编组 日常 WinAPI / 导出函数:文本、结构引用、回调 文本 / 文本A / &矩形 / 子程序指针
B. DLL支持 把 Y++ 值变成「地址整数」再塞进 .yp整数 形参 DLL_文本指针W/ADLL_整数指针
C. 指针操作 底层取址、读写任意内存、偏移 取整数指针地址取字节集指针地址指针到整数

推荐顺序: 能用 A 就用 A → 需要裸 int* / 手动 LPCWSTR 地址时用 B → 拼缓冲区 / 读已有内存用 C。

不要为指针再造一等类型(无「整数指针类型」「文本指针类型」关键字);地址一律用 长整数 / 整数 传递。


2. C / Win 类型 → Y++ 全表

2.1 标量(按值)

C / Win .yp 参数 / 返回 .yc
void 省略返回类型或写 无返回值调用
int / UINT / DWORD / INT_PTR / HWND / HANDLE 整数 整数
SHORT / WORD(16 位) 短整数 短整数
BYTE / unsigned char 字节 字节
BOOL 逻辑 逻辑
float 单浮点 单浮点
double 小数 小数
long long / SIZE_T(按整型传) 长整数整数 同左

2.2 文本(自动编组,优先)

C / Win .yp 说明
LPCWSTR / const wchar_t* / LPWSTR(入参) 文本 边界按宽字符传递
LPCSTR / const char* / LPSTR(入参) 文本A 边界按 UTF-8 窄串传递(与系统 ANSI 不完全等同)
返回 LPCWSTR 返回类型 文本 常见;注意生命周期由被调方保证

不要取文本指针地址 去对接普通 LPCWSTR:它取的是文本变量对象地址,不是宽串缓冲区。

2.3 结构体指针

C / Win Y++ 说明
RECT* / POINT* / 自定义 POD 结构指针 &类型名 / 类型名 &名 / 引用 类型名 名 类型须在 .yt 定义;出入参编组
结构内嵌 LPCWSTR.yt文本 字段) &类型名 已支持:打包为 LPCWSTR(入参,不回写)
const MSGBOXPARAMSA* 等窄串结构 &类型 + 窄指针字段 .yt 暂无 文本A 字段;窄串指针可用 整数 + DLL_文本指针A 填入,或后续再开 文本A 字段
const 修饰 忽略 调用约定上按指针传入即可,不新增类型

2.4 标量指针 / 缓冲区指针(无专用 .yp 类型)

.yp 没有 整数* / 字节* 关键字。统一策略:

  1. 形参声明为 整数(语义 = 地址)
  2. 调用时用 DLL支持指针操作 得到地址
C / Win 推荐拿地址方式 .yp 形参
int* / LPDWORD / INT_PTR*(出参) DLL_整数指针(变量)(或 取整数指针地址 整数
long long* 取长整数指针地址(变量) 整数 / 长整数
BYTE* / char* 二进制缓冲 取字节集指针地址(字节集) 整数
LPCWSTR 但想手动传地址 DLL_文本指针W(文本) 整数
LPCSTR 手动传地址 DLL_文本指针A(文本) 整数
float* / double* 取小数指针地址 等 + 自行约定 整数
BOOL* 取逻辑指针地址 或单字段 .yt 整数&结构

2.5 函数指针 / 回调

C / Win Y++ 注意
WNDENUMPROC / FARPROC / 回调 子程序指针 名 不要& / 引用
传入用户函数 .yc&函数名 与「子程序指针」形参配对
按任意地址 Call(插件返回的函数指针) 调用函数Ex(地址, …) / DLL_调用* 见 §6;先 取导出函数 或插件返回地址

2.6 数组

情况 做法
.yp 字节数组(字节数组缓冲) 形参写 字节 名[].yc 声明 字节 名[] 直接传入
.yp 字节集 形参写 字节集 名(勿加 []),亦可
.yp 其它元素数组 凡可作元素的标量均写 类型 名[]整数/长整数/短整数/逻辑/小数/双浮点/单浮点
.yt 内嵌数组字段 见 usertype;经 &结构 时数组字段当前也可能受限
旧写法(仍可用) .yp整数 地址 + DLL_字节集指针 / 取字节集指针地址
Y++ 数组对象地址(慎用) 取数组指针地址

3. 按「指针种类」拆开说明

3.1 整数指针(int* / 出参)

专用命令: DLL_整数指针(整数变量)(支持库 → DLL支持

// .yp
kernel32 逻辑 GetExitCodeProcess(整数 进程句柄, 整数 退出码指针) 取进程退出码指针

// .yc
整数 code = 0
取进程退出码指针(取当前进程(), DLL_整数指针(code))
输出(到文本(code))   // 调用后直接读变量

等价底层:取整数指针地址(code)(在 指针操作 分类下,语义偏通用取址)。

备选: 单字段结构体 + &整数盒子(适合想走 .yp UserRef 编组时)。

3.2 文本指针(宽 / 窄)

需求 命令 备注
日常 MessageBoxW(..., LPCWSTR, ...) .yp 直接写 文本 首选,勿绕路
日常窄串 API .yp文本A UTF-8
形参已写成「整数=地址」 DLL_文本指针W / DLL_文本指针A A 用 TLS 环形缓冲,同句可多次
读内存里的宽/窄串 指针到文本W / 指针到文本A 指针操作
整数 n = 宽串长度指针(DLL_文本指针W("hello"))
整数 m = 窄串长度指针(DLL_文本指针A("abc"))

易错: 取文本指针地址(文本变量)LPCWSTR。DLL 边界请用 文本 / DLL_文本指针W

3.3 字节集指针(缓冲区)

DLL_字节集指针(字节集变量)取字节集指针地址 等价,DLL 边界推荐前者:

字节集 buf
' ... 写入内容 ...
长整数 p = DLL_字节集指针(buf)   // 空字节集返回 0
某DLL读缓冲(p, 字节集长度(buf))

读回:指针到字节集(地址, 长度);写入:指针写字节集

3.4 其它标量取址(指针操作)

命令 对象
取字节指针地址 字节 变量(对象地址)
取短整数(无单独命令时) 用结构体或字节集布局
取长整数指针地址 长整数
取小数指针地址 小数
取逻辑指针地址 逻辑
取通用指针地址 通用
取数组指针地址 数组对象地址

读写:指针写整数 / 指针到整数 / 指针写长整数 / 指针偏移 / 指针是否可读 等。

3.5 结构体指针(.yt + &

// .yt
矩形 {
    整数 left = 0
    整数 top = 0
    整数 right = 0
    整数 bottom = 0
}

// .yp
user32 逻辑 GetWindowRect(整数 窗口句柄, &矩形 框) 取窗口矩形

// .yc
矩形 r
取窗口矩形(主窗口.句柄, r)

限制: 结构内的 字节集 / 嵌套用户类型 / 数组 字段,当前 & 编组仍会跳过
文本 字段已编组为入参 LPCWSTR(指向 Y++ 侧宽串,调用期间有效;不回写)。窄串 LPCSTR 字段请用 整数 + DLL_文本指针A,或等后续 文本A 字段类型。

3.6 const

写法 处理
const MSGBOXPARAMSA * 与非 const 指针相同:按指针传入
const char* 文本ADLL_文本指针A
API 转 Y++ 转换器会剥掉 const / CONST

单独增加 const 类型关键字。


4. DLL支持 vs 指针操作(对照)

场景 用 DLL支持 用 指针操作
给 DLL 的 LPCWSTR 地址 DLL_文本指针W (不推荐 取文本指针地址
给 DLL 的 UTF-8 LPCSTR DLL_文本指针A 自行转字节集再取址
给 DLL 的 int* 出参 DLL_整数指针 取整数指针地址
二进制缓冲首址 DLL_字节集指针 / 取字节集指针地址 二者等价;DLL 边界优先 DLL_字节集指针
读/写任意地址 指针到* / 指针写*
地址加减 指针偏移 / 取指针地址

设计原则:DLL_ = 边界友好、命名即用途;指针操作* = 通用内存工具。


5. 库名(user32 / @"user32.dll")能不能省略?

5.1 运行时真相

每个 .yp 函数最终必须知道 从哪个 DLL LoadLibrary
不能「完全不写库、运行时魔法猜对所有 API」——系统无法从导出名 100% 唯一映射到 DLL(第三方插件更不可能)。

5.2 现在允许的省略方式

写法 是否要写库 说明
@"user32.dll" 后跟无短名的声明 文件内切一次即可 后续声明跟「当前库」
user32 MessageBoxW(...) 消息框 短名即可,等价 user32.dll 不必写 @"..."
MessageBoxW(...) 消息框 @"user32.dll" 别名后写库 单条自带库
完全不写、也不靠当前库 不行 无法解析

5.3 「API 转 Y++ 声明」已做的自动化

转换器会:

  1. 猜测导出名所属 DLL(表驱动 + 启发式,如 MessageBox*→user32,CreateFile*→kernel32)
  2. 输出里自动插入 @\"xxx.dll\" 并分组
  3. 合并进已有 .yp 时:已有库不再重复插入,已有别名跳过

因此:用户不必手打 @"user32.dll"——转换成功时会自动生成。

5.4 局限(需心里有数)

  • 猜错时默认常落到 user32.dll(启发式兜底)→ 第三方 DLL / 冷门 API 必须人工改库名
  • 无法从 C 声明 alone 推断「我的插件.dll」
  • 运行时仍然依赖声明里的库字段;省略的是「手工输入」,不是「声明里彻底没有库」

6. 按地址 Call / 动态 DLL 调用(已实现)

支持库分类:基础支持库 → DLL支持

6.1 核心命令

命令 作用
加载DLL / LoadLibrary 加载模块 → 长整数句柄
释放DLL / FreeLibrary 释放模块
取导出函数 GetProcAddress → 入口地址
调用函数Ex(地址, …) 按地址动态调用(≤16 参);也可 调用函数Ex("Y++函数名", …)
DLL_调用 / DLL_调用整数 / DLL_调用文本 按 DLL 名 + 导出名调用
DLL_参数(类型, 值) 标明 文本W/A、整数指针、地址等
DLL_申请内存 / 读写 / 缓冲区系列 手动缓冲与安全缓冲区
DLL_内存加载 / DLL_写出 / 置DLL约定 / DLL_取错误 内存映射、落盘、约定、错误

6.2 示例

长整数 u = LoadLibrary("user32.dll")
长整数 p = 取导出函数(u, "MessageBoxW")
调用函数Ex(p, 0, DLL_参数("文本W", "你好"), DLL_参数("文本W", "标题"), 0)
FreeLibrary(u)

整数 tick = DLL_调用整数("kernel32", "GetTickCount", "winapi")

裸文本传给 DLL 时默认 系统 ACP(兼容常见插件窄字符串约定);宽字符 / UTF-8 请用 DLL_参数("文本W"/"文本A"/"utf8", …)

6.3 注意

  • 参数过多(>16)、导出名错误:立刻看 DLL_取错误()
  • 回调:传 &函数名;cdecl 可用 DLL_回调(&函数名, "cdecl")(地址包装)
  • DLL_内存加载(":/dll/x.dll", "x.dll") 后可用注册名走 DLL_调用;位数须与程序一致

7. 场景速查

你想做的事 做法
MessageBoxW .yp文本;直接传字符串
lstrlenA / 窄串哈希 .yp文本A;或 整数 + DLL_文本指针A
GetWindowRect .yt 矩形 + &矩形
GetExitCodeProcess 出参 整数 形参 + DLL_整数指针
读文件到缓冲再交给 DLL 字节集 + 取字节集指针地址
EnumWindows 回调 子程序指针 + &回调函数
MessageBoxIndirectW 类(结构内 LPCWSTR .yt 文本字段 + &结构(已编组)
MessageBoxIndirectA 类(结构内 LPCSTR 窄指针用 整数 + DLL_文本指针A;或待 文本A 字段
插件返回的函数指针再 Call 调用函数Ex(地址, …)(§6 已实现)
const 指针参数 当普通指针;转换器去 const

8. 已实现 / 缺口清单

已实现

  • .yp文本 / 文本A / 标量 / &结构(含结构内 文本→LPCWSTR)/ 子程序指针 / 动态加载
  • DLL支持:DLL_文本指针W/ADLL_整数指针
  • DLL支持:加载DLL/取导出函数/调用函数Ex/DLL_调用*/DLL_调用数组(按元素类型打包)/DLL_参数/缓冲/内存映射等
  • 指针操作:取址、读写、偏移、字节集缓冲址
  • API 转 Y++:剥 const、猜 DLL、自动 @\"dll\"

仍可增强

说明
结构体内嵌 LPCSTR / .yt 文本A 字段 当前文本字段按宽 LPCWSTR;窄串用 整数+DLL_文本指针A
结构体内嵌字节集 / 嵌套类型 / 数组字段 &结构 仍跳过
更准的 API→DLL 映射表 扩大转换器字典
第三方 DLL 位数 工程架构须与 DLL 一致(x86 进程无法 加载DLL 加载 x64 插件,反之亦然)

9. 最小示例汇总

' --- 文本自动 ---
消息框(0, "你好", "标题", 0)

' --- 文本指针命令 ---
整数 nw = 宽串长度指针(DLL_文本指针W("Wide"))
整数 na = 窄串长度指针(DLL_文本指针A("narrow"))

' --- 整数出参 ---
整数 code = 0
取进程退出码指针(取当前进程(), DLL_整数指针(code))

' --- 字节集缓冲 ---
字节集 buf
长整数 p = 取字节集指针地址(buf)

' --- 结构引用 ---
矩形 r
取窗口矩形(主窗口.句柄, r)