返回列表

帖子详情

经验分享

Y++调用 Windows 系统 API 指南

作者:管理员发布:2026-08-11 01:50:46浏览:0
# `.ypi` 调用 Windows 系统 API 指南

`.ypi`**声明式 FFI**:把 DLL / WinAPI 的导出函数声明成可在 Y++ 里直接调用的中文(或英文)命令。  
适合:`user32` / `kernel32` / 自研 DLL / 第三方 C 导出。

---

## 文件类型说明(请勿混用)

| 扩展名 | 用途 | 本文是否涉及 |
|--------|------|--------------|
| **`.ypi`** | Windows / DLL API 声明(`DLL(...)`、导出名、中文别名) | **本文主体** |
| **`.yc`** | 源码中调用已声明的 API | 调用示例 |
| **`.yt`** | API 参数用到的结构体布局 | 结构体示例 |
| **`.ypp`** | 带方法的类 | 不涉及 |

---

## 1. 文件放哪

```
source/
  winapi.ypi          ← API 声明
  main.yc             ← 调用代码
  POINT.yt            ← 若参数含结构体,用 .yt 定义
```

`.ypi` 加入工程后自动加载,无需 `#include`。  
其中声明的 API(英文导出名与中文别名)在**本工程所有** `.yc` / `.ypp` / 其它可编译源文件中都可直接调用,相当于工程级全局命令,不必每个文件重复声明。

---

## 2. 最小例子:MessageBoxW

`source/winapi.ypi`

```ypi
DLL("user32.dll", "stdcall")

整数 MessageBoxW(整数 hWnd, 文本 内容, 文本 标题, 整数 类型) 信息框
```

`source/main.yc`

```yc
函数 按钮1.单击(整数 X, 整数 Y) {
    信息框(0, "你好,Windows API", "提示", 0)
}
```

说明:

- `DLL("user32.dll", "stdcall")`:指定模块与调用约定  
- 最后的 `信息框`**中文别名**(推荐,便于补全与调用)  
- `文本` 对应宽字符 `LPCWSTR`(UTF-16)

---

## 3. 声明语法

### 3.1 模块头

```ypi
DLL("user32.dll", "stdcall")
DLL("kernel32.dll", "stdcall")
```

- 第一参数:DLL 文件名或路径(系统目录 DLL 可只写文件名)  
- 第二参数:`stdcall`(WinAPI 常用)或 `cdecl`  
- x64 下约定差异较小,仍建议与头文件一致  

### 3.2 函数行

```ypi
[返回类型] 英文导出名(参数列表) 中文别名
```

示例:

```ypi
逻辑 Beep(整数 频率, 整数 时长) 蜂鸣
整数 GetTickCount() 取启动毫秒
整数 FindWindowW(文本 类名, 文本 标题) 寻找窗口
逻辑 SetWindowTextW(整数 hWnd, 文本 标题) 置窗口标题
整数 GetWindowTextW(整数 hWnd, 文本缓冲W 缓冲, 整数 最大字符数) 取窗口标题
```

规则:

- **英文导出名**必须是 DLL 真实导出(通常 ASCII)  
- **中文别名**建议必填,供 Y++ 源码调用  
- 参数名仅作文档,调用时按位置传参  

### 3.3 现代简写(无 DLL 行时)

部分工程也支持直接:

```ypi
逻辑 StartMouseTrail(整数 length, 单浮点 width, 文本A colorHex) 启动鼠标轨迹
```

再配合 `设置DLL路径` / `置DLL约定`(见下文多 DLL)。

---

## 4. 类型对照(WinAPI)

| C / WinAPI | `.ypi` 类型 | 说明 |
|------------|-------------|------|
| `BOOL` | `逻辑` | |
| `int` / `INT` / `DWORD` / `LONG` | `整数` | 4 字节 |
| `HWND` / `HANDLE` / 指针地址 | `整数``长整数` | 句柄作整数传;64 位地址优先 `长整数` |
| `int64_t` / `LONGLONG` | `长整数` | 8 字节 |
| `SHORT` / `WORD` | `短整数` | |
| `BYTE` | `字节` | |
| `float` | `单浮点` | |
| `double` | `双浮点` | |
| `LPCWSTR` / `const wchar_t*` | `文本` | UTF-16 |
| `LPCSTR` / `const char*` | `文本A` | UTF-8(声明式路径) |
| 可写 `wchar_t*` 缓冲 | `文本缓冲W` | |
| 可写 `char*` 缓冲 | `文本缓冲A` | |
| `int*` 等出参 | `整数指针` 等 | 直接传变量,勿再 `取变量地址` |
| 回调 | `子程序指针` | 传 `&函数名` |
| `void` | `空` / `无` | |
| 结构体指针 | `.yt` 类型名 | 先定义 `.yt` |

---

## 5. 结构体参数(配合 `.yt`

`source/几何.yt`

```yt
POINT {
    整数 x
    整数 y
}

RECT {
    整数 left
    整数 top
    整数 right
    整数 bottom
}
```

`source/winapi.ypi`

```ypi
DLL("user32.dll", "stdcall")

逻辑 PtInRect(RECT 矩形, POINT 点) 点在矩形内
```

`source/main.yc`

```yc
函数 按钮1.单击(整数 X, 整数 Y) {
    RECT r
    r.left = 0
    r.top = 0
    r.right = 100
    r.bottom = 50

    POINT p
    p.x = 10
    p.y = 20

    如果 (点在矩形内(r, p)) {
        输出("在内")
    }
}
```

注意:`.yt` 字段顺序/宽度必须与 SDK 一致;`整数`/`逻辑``.yt` 中按 4 字节布局。

---

## 6. 文本与缓冲

### 6.1 只读宽字符(最常见)

```ypi
逻辑 SetWindowTextW(整数 hWnd, 文本 标题) 置窗口标题
```

```ypp
置窗口标题(窗口句柄, "新标题")
```

### 6.2 需要写出缓冲(取文本)

```ypi
整数 GetWindowTextW(整数 hWnd, 文本缓冲W 缓冲, 整数 最大字符数) 取窗口标题W
```

调用时通常配合缓冲创建命令(以支持库实际命令为准),例如:

```ypp
// 概念示例:先创建宽字符缓冲,再传入取标题 API,再读回文本
```

窄字符 API 用 `文本A` / `文本缓冲A`。中文场景优先 **W 版 API**

---

## 7. 回调(子程序指针)

```ypi
DLL("user32.dll", "stdcall")

整数 EnumWindows(子程序指针 回调, 整数 lParam) 枚举窗口
```

```ypp
函数 枚举回调(整数 hWnd, 整数 lParam) 逻辑 {
    输出(hWnd)
    返回(真)   // 继续枚举
}

函数 按钮1.单击(整数 X, 整数 Y) {
    枚举窗口(&枚举回调, 0)
}
```

-`&函数名`  
- 回调形参类型必须与原生原型一致  
- 默认按 stdcall 桥接;若 DLL 要求 cdecl,按文档使用 `DLL_回调(&函数名, "cdecl")` 一类写法  

---

## 8. 多 DLL / 自定义路径

```ypp
函数 主窗口.创建完毕() {
    设置DLL路径(系统_取运行目录() + "\\plugins\\mydll.dll")
    置DLL约定("mydll.dll")   // 省略约定参数时多为 stdcall
    我的初始化()
}
```

- 系统 DLL(`user32.dll`)一般只需在 `.ypi` 写模块名  
- 自研 DLL:保证运行目录能找到,或 `设置DLL路径`  
- 资源路径 `:/xxx.dll`:会按规则内存加载或写出到 exe 旁再加载  

---

## 9. 与 `调用函数Ex` 的区别

| 方式 | 优点 | 缺点 |
|------|------|------|
| `.ypi` 声明 | 类型安全、补全、可读 | 需先写声明 |
| `调用函数Ex` / `LoadLibrary` | 灵活、临时探测 | 易错、文本编码默认 ACP |

正式工程优先 `.ypi`。临时调试可用动态调用,注意 A/W 编码。

---

## 10. 实用 WinAPI 声明片段

```ypi
DLL("user32.dll", "stdcall")

整数 MessageBoxW(整数 hWnd, 文本 内容, 文本 标题, 整数 类型) 信息框
整数 FindWindowW(文本 类名, 文本 标题) 寻找窗口
逻辑 ShowWindow(整数 hWnd, 整数 命令) 显示窗口
逻辑 SetWindowPos(整数 hWnd, 整数 hWndInsertAfter, 整数 x, 整数 y, 整数 cx, 整数 cy, 整数 flags) 置窗口位置
逻辑 GetWindowRect(整数 hWnd, RECT 矩形) 取窗口矩形

DLL("kernel32.dll", "stdcall")

整数 GetTickCount() 取启动毫秒
逻辑 Beep(整数 频率, 整数 时长) 蜂鸣
整数 GetCurrentProcessId() 取当前进程ID
```

`RECT` 需在 `.yt` 中定义。)

---

## 11. 排错

| 现象 | 排查 |
|------|------|
| 找不到命令 | `.ypi` 是否加入工程;别名是否写对 |
| 调用崩溃 | stdcall/cdecl、参数个数/类型、A/W 版本是否匹配 |
| 中文乱码 | 改用 W API + `文本`;避免窄字符 ACP 路径 |
| 结构体不对 | 检查 `.yt` 字段顺序与 4 字节整数布局 |
| 找不到 DLL | 路径、位数(x86/x64)是否与程序一致 |

---

## 12. 与其它文档

- 纯数据结构:`自定义数据类型_yt使用指南.md`  
- 带方法的类:`自定义类_ypp使用指南.md`  
- 更完整的第三方 DLL / 元数据说明:仓库 `docs/Y++调用外部DLL开发文档.md`

评论