如何获取strsafe.h并使其在Bellard开发的Tiny C Compiler中正常运行
解决方案
你遇到的报错本质是MinGW版本的strsafe.h依赖大量MinGW私有宏、微软SAL注解扩展,这些语法不被TCC支持,并非C标准兼容问题。以下是3种可行解决路径,按实施复杂度从低到高排序:
方案1:替换strsafe系列函数调用(最推荐)
strsafe.h是微软推出的安全字符串操作头文件,其提供的所有函数都可以用标准C函数配合简单的长度校验替代,无需引入额外头文件:
StringCchCopyW(dest, cchDest, src)替换为wcscpy_s(dest, cchDest, src),如果TCC未提供wcscpy_s,可自行补一行长度判断:if (wcslen(src) < cchDest) wcscpy(dest, src);StringCchPrintfW(dest, cchDest, format, ...)替换为swprintf(dest, cchDest, format, ...)- 其余strsafe函数均可对应到标准wchar.h、string.h中的函数,仅需补充目标缓冲区长度校验逻辑即可。
修改完成后直接删除源码中#include <strsafe.h>的声明即可正常编译。
方案2:使用TCC兼容的精简strsafe.h
无需引入MinGW整套依赖头文件,自行实现项目用到的strsafe函数即可,操作步骤如下:
- 在你的项目根目录新建名为
strsafe.h的文件,写入以下内容:
#ifndef STRSAFE_H_INCLUDED #define STRSAFE_H_INCLUDED #include <wchar.h> #include <string.h> #include <stdarg.h> #define STRSAFE_E_INSUFFICIENT_BUFFER 0x8007007A #define STRSAFE_E_INVALID_PARAMETER 0x80070057 #define S_OK 0 static inline int StringCchCopyW(wchar_t *dest, size_t cchDest, const wchar_t *src) { if (dest == NULL || cchDest == 0 || src == NULL) return STRSAFE_E_INVALID_PARAMETER; size_t srcLen = wcslen(src); if (srcLen >= cchDest) { wcsncpy(dest, src, cchDest - 1); dest[cchDest - 1] = L'\0'; return STRSAFE_E_INSUFFICIENT_BUFFER; } wcscpy(dest, src); return S_OK; } static inline int StringCchPrintfW(wchar_t *dest, size_t cchDest, const wchar_t *format, ...) { if (dest == NULL || cchDest == 0 || format == NULL) return STRSAFE_E_INVALID_PARAMETER; va_list args; va_start(args, format); int ret = vswprintf(dest, cchDest, format, args); va_end(args); if (ret < 0 || (size_t)ret >= cchDest) return STRSAFE_E_INSUFFICIENT_BUFFER; return S_OK; } // 按需补充其他你用到的strsafe函数实现即可 #endif
- 编译时添加
-I.参数,让TCC优先读取项目目录下的自定义头文件,编译命令示例:tcc -run -I. main.c
方案3:修复MinGW版本strsafe.h的编译错误
如果你坚持使用MinGW版本的strsafe.h,可通过预定义空宏的方式消除TCC不识别的扩展语法:
- 在你的源码中
#include <strsafe.h>之前加入以下宏定义:
#define __in #define __out #define _In_ #define _Out_ #define _In_z_ #define _Out_writes_z_(x) #define __MINGW_EXTENSION #define __drv_preferredFunction(...) #define __drv_when(...) // 编译时如果遇到其他未知标识符报错,直接将对应的宏名加在此处定义为空即可
- 之前引入的MinGW依赖头文件无需删除,添加上述宏后即可正常编译。
内容的提问来源于stack exchange,提问作者user3789797
相关产品推荐
相关产品推荐

