Fun 语言 Win32API 便利接口
..
作者: 一了 <
[email protected]
> 日期: 2026-05-01 一年一度的劳动节又来了, 这次勤劳勇敢的小蜜蜂给大家带了 Fun 语言便利的 Win32 接口调用, 如下:
# Fun 语言 Win32 互操作库 这是一套轻量、现代化的 Windows API 调用框架,让 Fun 语言能够**直接粘贴 C 声明,零手工翻译**完成结构体映射、API 调用、回调生成和汇编执行。 它已在 ANSI 和 Unicode 环境下通过完整测试。 --- ## 核心特性 - **C 声明即接口**:粘贴 `struct` 或函数原型,自动解析类型、对齐、签名,无需手写 flag 字符串。 - **跨平台内存布局**:基于十六进制中间表示,完美兼容 ANSI/Unicode,结构体读写正确。 - **`args` 混合容器**:参数可通过名字或索引访问,支持 `init` 一次性初始化,无名参数也能用数组语法赋值。 - **回调现代化**:`@callback` 将 C 函数指针声明 + Fun 函数自动转换为原生回调指针,支持 `thread`、`obj` 等选项。 - **多线程安全**:`call` 方法通过 `opts` 传递 `thread: true`,保证子线程回调正常运行。 - **注释剥离**:自动去除 `//` 和 `/* */` 注释,从 MSDN 复制原型即可直接使用。 - **便捷汇编**:`@asm` 一行执行 x86 汇编代码,自动管理可执行内存。 - **输出参数自动刷新**:结构体指针参数调用后自动 `toFun()`,字符串输出缓冲区也可自动提取内容(ANSI/Unicode 适应)。 - **结构体高级特性**:支持 `@size` 元数据自动填充结构体大小、`customSize` 变长结构体、嵌套结构体(内联或指针)。 - **字符串生命周期管理**:`str_ptr` 输入的临时字符串自动缓存,防止被 GC 回收。 --- ## 一句话总结 **用 C 语言的方式声明,用脚本语言的方式调用,无需翻译,跨平台兼容。** --- ## 用法举例 ### 1. 结构体序列化/反序列化 ```fun use "lib-cstruct.fun"; // 注册结构体(名称 + C 声明) CStruct.@register('POINT', 'struct POINT { int x; int y; }'); // 构造并初始化 var pt = CStruct('struct POINT { int x; int y; }', [ x: 100, y: 200 ]); // 序列化为内存指针 var ptr = pt.@toPtr(); // 从内存反序列化 pt.@toFun(); ?. pt.x; // 100 ?. pt.y; // 200 ``` **带 `@size` 自动填充大小字段**: ```fun var cls = CStruct('struct WNDCLASSEX { UINT cbSize; ... }', [ '@size': 'cbSize', style: CS_HREDRAW ]); cls.@toPtr(); // cbSize 自动设为结构体大小 ``` **变长结构体**: ```fun var bi = CStruct('struct BITMAPINFO { ... }', nil, 1024); // 强制 1024 字节 ``` ### 2. 调用 API(MessageBox) ```fun use "lib-cwinapi.fun"; // 声明 API(自动解析原型、获取函数地址) var msg = CWin32API('user32.dll', 'int MessageBox(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);'); // 通过 args 赋值 msg.args.hWnd = 0; msg.args.lpText = 'Hello from Fun!'; msg.args.lpCaption = 'Test'; msg.args.uType = 0; // 调用 msg.call(); ``` **带参数覆盖的调用**(不修改 args 的默认值): ```fun // 仅临时替换按钮类型和标题 msg.call([lpText: 'New Text', uType: 0x10]); // 再次调用时仍使用 args 中的原始值 msg.call(); ``` ### 3. 回调函数(EnumWindows) ```fun use "lib-cwinapi.fun"; // 定义 Fun 回调函数 fun enumProc(hWnd, lParam) ?. "窗口句柄: " & hWnd; return 1; // 继续枚举 end fun; // 声明带回调的 API var enumWin = CWin32API('user32.dll', 'BOOL EnumWindows(BOOL CALLBACK (HWND, LPARAM) lpEnumFunc, LPARAM lParam);'); // 直接赋值 Fun 函数,自动生成回调指针 enumWin.args.lpEnumFunc = enumProc; enumWin.args.lParam = 0; enumWin.call(); ``` ### 4. 创建线程(CreateThread + 多线程安全) ```fun use "lib-cwinapi.fun"; fun threadFunc(param) ?. "线程运行,参数: " & param; return 0; end fun; var proto = 'HANDLE CreateThread(LPSECURITY_ATTRIBUTES, DWORD, DWORD WINAPI (LPVOID), LPVOID, DWORD, LPDWORD);'; // 通过 init 初始化(无名参数按顺序赋值) var create = CWin32API('kernel32.dll', proto, [ 0, 0, // lpThreadAttributes, dwStackSize threadFunc, // lpStartAddress(自动转回调) 42, // lpParameter 0, nil // dwCreationFlags, lpThreadId ]); // 调用时传递 thread 标志 var hThread = create.call(opts: [thread: true]); ?. "线程句柄: " & hThread; ``` ### 5. 内嵌汇编(CPUID) ```fun use "lib-cwinapi.fun"; use "lib-asm-pro.fun"; // 提供 Assembly var code = `#!asm pop ebx pop eax push eax push ebx push edi mov edi, eax mov eax, $00000001 cpuid push eax stosd mov eax, edx stosd pop eax pop edi `; var cpu = ' '.x(8 div charSize()); // 输出缓冲区 CWin32API.@asm(Assembly, 'i:i', code, cpu.toNum(-1)); ?. str2hex(cpu); // 打印 CPU ID ``` --- ## 更多 本库由 `lib-cstruct.fun`(结构体引擎)和 `lib-cwinapi.fun`(API 封装)组成,依赖 `lib-os.fun`、`lib-regex.fun` 等基础库。它使得 Fun 语言在 Windows 系统编程中获得了媲美 C 语言的表达力,同时保留了脚本语言的即时性。