寻求可动态链接、提供fprintf等C运行时函数的Windows DLL
问题描述
当前Windows SDK不再提供包含大量C运行时函数的DLL,在ucrtbase.dll中能找到fopen,但找不到fprintf。查看stdio头文件,发现fprintf是内联定义:
_Check_return_opt_ _CRT_STDIO_INLINE int __CRTDECL fprintf( _Inout_ FILE* const _Stream, _In_z_ _Printf_format_string_ char const* const _Format, ...) #if defined _NO_CRT_STDIO_INLINE ; #else { int _Result; va_list _ArgList; __crt_va_start(_ArgList, _Format); _Result = _vfprintf_l(_Stream, _Format, NULL, _ArgList); __crt_va_end(_ArgList); return _Result; } #endif
若定义_NO_CRT_STDIO_INLINE会出现链接失败的问题,搜索到的legacy_stdio_definitions.lib仅适用于静态链接,现需实现C运行时函数的动态链接。
解决方案
不要定义
_NO_CRT_STDIO_INLINE宏
现代UCRT的设计就是将fprintf这类标准函数以inline形式实现,内部调用ucrtbase.dll中导出的底层函数(比如上述代码里的_vfprintf_l)。保留内联定义的情况下,编译后的代码会直接调用ucrtbase.dll的导出函数,自然实现动态链接,无需额外处理。手动动态绑定底层导出函数(若需显式加载UCRT)
如果需要手动加载ucrtbase.dll并获取函数地址,可直接绑定fprintf依赖的底层导出函数,自己封装上层实现:#include <windows.h> #include <stdio.h> #include <stdarg.h> // 定义底层函数类型 typedef int(*VFPFINT_L)(FILE*, const char*, _locale_t, va_list); VFPFINT_L p_vfprintf_l = NULL; // 封装自定义fprintf int my_fprintf(FILE* stream, const char* format, ...) { if (!p_vfprintf_l) return -1; va_list args; va_start(args, format); int ret = p_vfprintf_l(stream, format, NULL, args); va_end(args); return ret; } int main() { // 加载ucrtbase.dll HMODULE hUcrt = LoadLibraryA("ucrtbase.dll"); if (hUcrt) { // 获取底层函数地址 p_vfprintf_l = (VFPFINT_L)GetProcAddress(hUcrt, "_vfprintf_l"); if (p_vfprintf_l) { my_fprintf(stdout, "Hello, dynamic link!\n"); } FreeLibrary(hUcrt); } return 0; }关于
legacy_stdio_definitions.lib
这个库是为了兼容旧版代码(比如依赖非内联C标准函数符号的代码),仅支持静态链接UCRT的场景,不适合动态链接需求,所以无需使用。
内容的提问来源于stack exchange,提问作者pm100
相关产品推荐
相关产品推荐

