未解析的外部符号 __imp__fprintf 和 __imp____iob_func,SDL2

unresolved external symbol __imp__fprintf and __imp____iob_func, SDL2

提问人:RockFrenzy 提问时间:5/23/2015 最后编辑:RockFrenzy 更新时间:6/2/2023 访问量:162635

问:

有人可以解释一下

__imp__fprintf

__imp____iob_func

未解决的外部手段?

因为我在尝试编译时遇到以下错误:

1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp__fprintf referenced in function _ShowError
1>SDL2main.lib(SDL_windows_main.obj) : error LNK2019: unresolved external symbol __imp____iob_func referenced in function _ShowError
1>E:\Documents\Visual Studio 2015\Projects\SDL2_Test\Debug\SDL2_Test.exe : fatal error LNK1120: 2 unresolved externals

我已经可以说问题不在于链接错误。我已经正确地链接了所有内容,但由于某种原因它无法编译。

我正在尝试使用 SDL2。

我使用 Visual Studio 2015 作为编译器。

我已经在 Linker -> Input -> Additional Dependencies 中链接到 SDL2.lib 和 SDL2main.lib,并确保 VC++ 目录正确无误。

C++ SDL-2 Visual-Studio-2015 未解析外部

评论


答:

-1赞 RockFrenzy 5/24/2015 #1

我设法解决了这个问题。

错误的来源是这行代码,可以在 SDLmain 源代码中找到。

fprintf(stderr, "%s: %s\n", title, message);

因此,我所做的就是在SDLmain中编辑该行的源代码:

fprintf("%s: %s\n", title, message);

然后,我构建了 SDLmain,并将 SDL2 库目录中的旧 SDLmain.lib 复制并替换为新构建和编辑的 SDLmain.lib。

然后,当我使用 SDL2 运行程序时,没有出现任何错误消息,并且代码运行顺利。

我不知道这以后会不会咬我,但一切都很顺利。

评论

1赞 Ross Ridge 5/24/2015
您的更改本身就是一个错误,不会解决您的问题中描述的问题。您不再收到链接器错误只是一个巧合,这可能完全是您如何重建库的结果。
0赞 RockFrenzy 5/24/2015
@RossRidge,哦,是的,可能就是这样。嗯,好吧。
143赞 god 6/17/2015 #2

我终于弄清楚为什么会这样了!

在 Visual Studio 2015 中,stdin、stderr、stdout 定义如下:

#define stdin  (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))

但以前,它们被定义为:

#define stdin  (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])

因此,现在不再定义__iob_func这会导致使用使用早期版本的 Visual Studio 编译的 .lib 文件时出现链接错误。

要解决此问题,您可以尝试定义自己,它应该返回一个包含 .__iob_func(){*stdin,*stdout,*stderr}

关于有关 stdio 函数的其他链接错误(在我的情况下是),您可以将 legacy_stdio_definitions.lib 添加到链接器选项中。sprintf()

评论

1赞 Steven R. Loomis 7/31/2015
感谢您追踪此事。IIRC {*stdin,*stdout,*stderr} 的问题可能是不同的编译单元可能有其“自己的”stdin 副本,这就是直接调用这些函数的原因。
3赞 Vargas 8/3/2015
这也为我解决了问题,只是在声明/定义中使用提醒。extern "C"
4赞 Milan Babuškov 8/8/2015
有人能准确地写出替换函数应该是什么样子吗?我尝试了不同的变体,但不断出现编译错误。谢谢。
61赞 PoL0 11/17/2015
extern "C" { FILE __iob_func[3] = { *stdin,*stdout,*stderr }; }
2赞 Hans Olsson 2/15/2018
上面iob_func定义不起作用,有关正确定义,请参阅 MarkH 的答案。(不能只将函数定义为数组并期望调用正常工作。
28赞 user5157912 7/27/2015 #3

我在VS2015中遇到了同样的问题。我通过在 VS2015 中编译 SDL2 源代码解决了它。

  1. 转到 http://libsdl.org/download-2.0.php 并下载 SDL 2 源代码。
  2. VS2015 中打开 SDL_VS2013.sln。系统将要求您转换项目。做吧。
  3. 编译 SDL2 项目。
  4. 编译 SDL2main 项目。
  5. 在 VS2015 的 SDL 2 项目中使用新生成的输出文件 SDL2main.lib、SDL2.lib 和 SDL2.dll。

评论

5赞 Joe 7/28/2015
顺便说一句,构建 SDL 2.0.3 需要安装 2010 年 6 月的 DirectX SDK。
2赞 kgwong 8/5/2015
为我工作,谢谢!!但我只需要编译和复制SDL2mainSDL2main.lib
8赞 Vhaerun Of Decrepitude 8/9/2015 #4

此问题的最新解决方案:使用更新的 sdl 库

"https://buildbot.libsdl.org/sdl-builds/sdl-visualstudio/?C=M;O=D"

他们似乎已经解决了这个问题,尽管它只是 32 位库(我认为)。

66赞 smartsl 9/8/2015 #5

对于国际海事组织的米兰·巴布什科夫(Milan Babuškov)来说,这正是替换功能应该是什么样子的:-)

FILE _iob[] = {*stdin, *stdout, *stderr};

extern "C" FILE * __cdecl __iob_func(void)
{
    return _iob;
}

评论

5赞 paulm 9/16/2015
只是缺少 MSVC 和 MSVC 版本 < 2015 的 #ifdef
1赞 Hans Olsson 1/13/2017
正如 MarkH 在另一个看起来正确但行不通的答案中指出的那样。
4赞 Jesse Chisholm 9/1/2017
@paulm我想你的意思是.#if defined(_MSC_VER) && (_MSC_VER >= 1900)
0赞 Juan 6/10/2022
我使用 Visual Studio 2022,并恢复了在 Visual Studio 2013 上创建的项目。我遇到了这个问题,通过添加代码“FILE _iob[]....”为我解决了__iob_func的问题。我遇到了另一个问题__vsnprintf通过在链接编辑器>条目>其他依赖项中添加“legacy_stdio_definitions.lib”来解决。
0赞 user2699548 9/22/2015 #6

当您链接到 msvcrt.dll 而不是 msvcr10.dll(或类似)时,可能会发生这种情况,这是一个很好的计划。因为它可以让你在最终软件包中重新分发 Visual Studio 的运行时库。

该解决方法对我有帮助(在Visual Studio 2008中):

#if _MSC_VER >= 1400
#undef stdin
#undef stdout
#undef stderr
extern "C" _CRTIMP extern FILE _iob[];
#define stdin   _iob
#define stdout  (_iob+1)
#define stderr  (_iob+2)
#endif

Visual Studio 6 及其编译器不需要此代码片段。因此,#ifdef。

2赞 SolutionIsComing 10/20/2015 #7

将预编译的 SDL2main.lib 和 SDL.lib 用于 VS2015 项目的库:https://buildbot.libsdl.org/sdl-builds/sdl-visualstudio/sdl-visualstudio-2225.zip

34赞 MarkH 1/7/2016 #8

如上所述,正确的答案是使用 VS2015 编译所有内容,但出于兴趣,以下是我对问题的分析。

这个符号似乎没有在Microsoft作为VS2015的一部分提供的任何静态库中定义,这是相当奇特的,因为所有其他符号都是。为了找出原因,我们需要查看该函数的声明,更重要的是,它是如何使用的。

下面是 Visual Studio 2008 标头中的代码片段:

_CRTIMP FILE * __cdecl __iob_func(void);
#define stdin (&__iob_func()[0])
#define stdout (&__iob_func()[1])
#define stderr (&__iob_func()[2])

因此,我们可以看到该函数的工作是返回 FILE 对象数组的开头(不是句柄,“FILE *”是句柄,FILE 是存储重要状态好东西的底层不透明数据结构)。此函数的用户是三个宏 stdin、stdout 和 stderr,它们用于各种 fscanf、fprintf 样式调用。

现在,让我们看一下 Visual Studio 2015 如何定义相同的内容:

_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#define stdin (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))

因此,替换函数的方法已更改,现在返回文件句柄而不是文件对象数组的地址,并且宏已更改为仅调用传入标识号的函数。

那么,为什么他们/我们不能提供兼容的 API? 有两条关键规则Microsoft不能违反其通过__iob_func的原始实现:

  1. 必须有一个包含三个 FILE 结构的数组,这些结构可以像以前一样进行索引。
  2. FILE 的结构布局无法更改。

上述任何一项的任何更改都意味着,如果调用该 API,与之链接的现有编译代码将出现严重错误。

让我们看一下 FILE 是如何定义的。

首先VS2008 FILE定义:

struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;

现在是VS2015 FILE定义:

typedef struct _iobuf
{
    void* _Placeholder;
} FILE;

所以问题的关键在于:结构已经改变了形状。引用__iob_func的现有编译代码依赖于这样一个事实,即返回的数据既是可以索引的数组,又是该数组中元素之间的距离相同。

由于以下几个原因,上述答案中提到的可能解决方案将不起作用(如果调用):

FILE _iob[] = {*stdin, *stdout, *stderr};

extern "C" FILE * __cdecl __iob_func(void)
{
    return _iob;
}

FILE 数组_iob将使用 VS2015 进行编译,因此它将被布置为包含 void* 的结构块。假设 32 位对齐,这些元素将相距 4 个字节。因此,_iob[0] 位于偏移量 0,_iob[1] 位于偏移量 4,_iob[2] 位于偏移量 8。相反,调用代码会期望 FILE 更长,在我的系统上对齐为 32 个字节,因此它将获取返回数组的地址并添加 0 个字节以获得元素零(那个是可以的),但对于 _iob[1],它将推断它需要添加 32 个字节,对于 _iob[2],它将推断它需要添加 64 个字节(因为它看起来就是这样在 VS2008 标头中)。事实上,VS2008 的反汇编代码证明了这一点。

上述解决方案的第二个问题是它复制了 FILE 结构 (*stdin) 的内容,而不是 FILE * 句柄。因此,任何 VS2008 代码都会查看与 VS2015 不同的底层结构。如果结构仅包含指针,这可能会起作用,但这是一个很大的风险。无论如何,第一个问题使这无关紧要。

我唯一能想到的技巧是__iob_func遍历调用堆栈以找出他们正在寻找的实际文件句柄(基于添加到返回地址的偏移量)并返回一个计算值,以便它给出正确的答案。这听起来很疯狂,但下面列出了仅适用于 x86(不是 x64)的原型供您娱乐。它在我的实验中工作正常,但您的里程可能会有所不同 - 不建议用于生产!

#include <windows.h>
#include <stdio.h>
#include <dbghelp.h>

/* #define LOG */

#if defined(_M_IX86)

#define GET_CURRENT_CONTEXT(c, contextFlags) \
  do { \
    c.ContextFlags = contextFlags; \
    __asm    call x \
    __asm x: pop eax \
    __asm    mov c.Eip, eax \
    __asm    mov c.Ebp, ebp \
    __asm    mov c.Esp, esp \
  } while(0);

#else

/* This should work for 64-bit apps, but doesn't */
#define GET_CURRENT_CONTEXT(c, contextFlags) \
  do { \
    c.ContextFlags = contextFlags; \
    RtlCaptureContext(&c); \
} while(0);

#endif

FILE * __cdecl __iob_func(void)
{
    CONTEXT c = { 0 };
    STACKFRAME64 s = { 0 };
    DWORD imageType;
    HANDLE hThread = GetCurrentThread();
    HANDLE hProcess = GetCurrentProcess();

    GET_CURRENT_CONTEXT(c, CONTEXT_FULL);

#ifdef _M_IX86
    imageType = IMAGE_FILE_MACHINE_I386;
    s.AddrPC.Offset = c.Eip;
    s.AddrPC.Mode = AddrModeFlat;
    s.AddrFrame.Offset = c.Ebp;
    s.AddrFrame.Mode = AddrModeFlat;
    s.AddrStack.Offset = c.Esp;
    s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
    imageType = IMAGE_FILE_MACHINE_AMD64;
    s.AddrPC.Offset = c.Rip;
    s.AddrPC.Mode = AddrModeFlat;
    s.AddrFrame.Offset = c.Rsp;
    s.AddrFrame.Mode = AddrModeFlat;
    s.AddrStack.Offset = c.Rsp;
    s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
    imageType = IMAGE_FILE_MACHINE_IA64;
    s.AddrPC.Offset = c.StIIP;
    s.AddrPC.Mode = AddrModeFlat;
    s.AddrFrame.Offset = c.IntSp;
    s.AddrFrame.Mode = AddrModeFlat;
    s.AddrBStore.Offset = c.RsBSP;
    s.AddrBStore.Mode = AddrModeFlat;
    s.AddrStack.Offset = c.IntSp;
    s.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif

    if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
    {
#ifdef LOG
        printf("Error: 0x%08X (Address: %p)\n", GetLastError(), (LPVOID)s.AddrPC.Offset);
#endif
        return NULL;
    }

    if (s.AddrReturn.Offset == 0)
    {
        return NULL;
    }

    {
        unsigned char const * assembly = (unsigned char const *)(s.AddrReturn.Offset);
#ifdef LOG
        printf("Code bytes proceeding call to __iob_func: %p: %02X,%02X,%02X\n", assembly, *assembly, *(assembly + 1), *(assembly + 2));
#endif
        if (*assembly == 0x83 && *(assembly + 1) == 0xC0 && (*(assembly + 2) == 0x20 || *(assembly + 2) == 0x40))
        {
            if (*(assembly + 2) == 32)
            {
                return (FILE*)((unsigned char *)stdout - 32);
            }
            if (*(assembly + 2) == 64)
            {
                return (FILE*)((unsigned char *)stderr - 64);
            }

        }
        else
        {
            return stdin;
        }
    }
    return NULL;
}

评论

4赞 Mohamed BOUZIDI 7/22/2017
就我而言,我需要从 Visual Studio 2013 升级许多项目(C++ 和 C# 项目)才能使用 Visual Studio 2015 Update 3。我想在构建 C++ 项目时保留 VC100(Visual Studio 2010 C++ 编译器),但我有与上述相同的错误。我通过将 legacy_stdio_definitions.lib 添加到链接器来修复 imp_fprintf。我怎样才能解决_imp____iob_func
7赞 Volker 2/2/2016 #9

链接意味着无法正常工作。深入研究 VS2012 和 VS2015 的 stdio.h,以下内容对我有用。唉,你必须决定它是否应该适用于 { stdin, stdout, stderr } 之一,永远不要超过一个。

extern "C" FILE* __cdecl __iob_func()
{
    struct _iobuf_VS2012 { // ...\Microsoft Visual Studio 11.0\VC\include\stdio.h #56
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname; };
    // VS2015 has only FILE = struct {void*}

    int const count = sizeof(_iobuf_VS2012) / sizeof(FILE);

    //// stdout
    //return (FILE*)(&(__acrt_iob_func(1)->_Placeholder) - count);

    // stderr
    return (FILE*)(&(__acrt_iob_func(2)->_Placeholder) - 2 * count);
}
51赞 kingsb 4/9/2016 #10

Microsoft对此有特别说明(https://msdn.microsoft.com/en-us/library/bb531344.aspx#BK_CRT):

printf 和 scanf 系列函数现在是内联定义的。

所有 printf 和 scanf 函数的定义都是 内联移动到 stdio.hconio.h 和其他 CRT 标头中。 这是一项重大更改,会导致链接器错误 (LNK2019、 未解析的外部符号),用于声明这些内容的任何程序 在本地运行,而不包含相应的 CRT 标头。如果 可能,您应该更新代码以包含 CRT 标头(即 是,添加 #include ) 和内联函数,但如果你这样做 不想修改代码以包含这些头文件,或者 替代解决方案是向链接器添加一个额外的库 输入,legacy_stdio_definitions.lib

若要将此库添加到 IDE 中的链接器输入,请打开上下文 菜单中,选择“属性”,然后在“项目”中 “属性”对话框中,选择“链接器”,然后编辑“链接器输入”以添加 legacy_stdio_definitions.lib 添加到以分号分隔的列表中。

如果您的项目与使用 早于 2015 年的 Visual C++ 版本,链接器可能会报告 未解析的外部符号。这些错误可能与内部有关 _iob_iob_func或相关导入的 STDIO 定义 某些 STDIO 函数以 __imp_* 的形式出现。Microsoft 建议您使用最新的 Visual C++ 编译器和库的版本(当您升级 项目。如果库是源的第三方库 不可用,您应该从 第三方或将您对该库的使用封装到单独的库中 使用旧版本的 Visual C++ 编译器编译的 DLL 和库。

评论

11赞 bytecode77 3/5/2017
或者 - 但这并不能解决 - 是否也有用于此的旧库?#pragma comment(lib, "legacy_stdio_definitions.lib")__imp___iob_func
0赞 Marisol 8/9/2023
@bytecode77你还记得你是如何解决的吗?我在“__imp____acrt_iob_func”中遇到了类似的错误。提前致谢!
10赞 The XGood 5/11/2016 #11

我不知道为什么,但是:

#ifdef main
#undef main
#endif

根据我的经验,在包含之后但在您的主要应该修复它之前。

评论

1赞 Trevor Hart 10/7/2016
....好。。。。所以在尝试这个之前,我听得上对自己说,我不知何故怀疑这是否会起作用,但它完全做到了......你能解释一下为什么这有效吗......?
1赞 The XGood 10/20/2016
@TrevorHart我相信它未定义“错误”的 SDL 主要包含对“未定义”缓冲区的引用,如果您的缓冲区使用您的缓冲区,那么它运行良好。
2赞 Cheezmeister 8/12/2017
这是可怕的不良做法黑客,但它是 3 行,它有效,它使我不必费力地构建 SDL,所以......干得好。
1赞 The XGood 9/8/2017
@Cheezmeister 不良做法和黑客通常需要做任何事情。尤其是那些不应该需要它们的东西。
7赞 Luc Bloom 1/2/2018 #12

我的建议是不要(尝试)实施__iob_func。

修复这些错误时:

libpngd.v110.lib(pngrutil.obj) : error LNK2001: unresolved external symbol ___iob_func curllib.v110.lib(mprintf.obj) : error LNK2001: unresolved external symbol ___iob_func

我尝试了其他答案的解决方案,但最终,返回 C 数组与 Windows 内部 IOB 结构数组不匹配。@Volker 是对的,它永远不会对 或 中的一个以上起作用。FILE*stdinstdoutstderr

如果一个库实际上使用了其中一个流,它就会崩溃。只要你的程序不会导致库使用它们,你就永远不会知道。例如,当 PNG 元数据中的 CRC 不匹配时写入。(通常不是一个值得崩溃的问题)png_default_errorstderr

结论:如果 VS2012(平台工具集 v110/v110_xp)和 VS2015+ 库使用 stdin、stdout 和/或 stderr,则无法混合使用。

解决方案:使用当前版本的 VS 和匹配的平台工具集重新编译具有未解析符号的库。__iob_func

0赞 Zzirconium 3/22/2019 #13

为了给这个已经很丰富的线程带来更多的混乱,我碰巧在 fprintf 上遇到了同样未解决的外部问题

main.obj : error LNK2019: unresolved external symbol __imp__fprintf referenced in function _GenerateInfoFile

即使在我的情况下,它处于一个完全不同的上下文中:在 Visual Studio 2005 (Visual Studio 8.0) 下,错误发生在我自己的代码中(与我正在编译的代码完全相同),而不是第三方。

碰巧这个错误是由我的编译器标志中的/MD选项触发的。切换到 /MT 消除了该问题。这很奇怪,因为通常,静态链接 (MT) 比动态链接 (MD) 引发的问题更多......但以防万一它为其他人服务,我把它放在那里。

0赞 Henrik Haftmann 4/2/2019 #14

就我而言,此错误来自我的试验,以删除对 MSVC 版本依赖的运行时库 DLL(msvcr10.dll 左右)的依赖项和/或删除静态运行时库,以从我的可执行文件中删除多余的脂肪。

所以我使用 /NODEFAULTLIB 链接器开关、我自制的“msvcrt-light.lib”(在需要时谷歌搜索)和 / 条目。mainCRTStartup()WinMainCRTStartup()

恕我直言,自 Visual Studio 2015 以来,所以我坚持使用较旧的编译器。

但是,定义符号_NO_CRT_STDIO_INLINE消除了所有麻烦,并且一个简单的“Hello World”应用程序仍然很小 3 KB,并且不依赖于不寻常的 DLL。 在 Visual Studio 2017 中测试。

4赞 soen.kr 5/23/2019 #15

我用以下功能解决了这个问题。我使用 Visual Studio 2019。

FILE* __cdecl __iob_func(void)
{
    FILE _iob[] = { *stdin, *stdout, *stderr };
    return _iob;
}

因为 stdin 宏定义了函数调用,“*stdin”表达式不能使用全局数组初始值设定项。但是局部数组初始值是可能的。 对不起,我的英语很差。

评论

0赞 Niki Romagnoli 6/9/2022
包裹在外部“C”工作。
2赞 Sisir 6/21/2019 #16

对于仍在寻找上述技巧不起作用的答案的任何人。静态链接是解决这个问题的方法。更改运行时库设置,如下所示

Project properties --> C/C++ --> Code generation --> Runtime Library --> Multi-threaded Debug (/MTd) instead of /MDd

以下是有关此解决方案的讨论: https://social.msdn.microsoft.com/Forums/vstudio/en-US/4a1c9610-fa41-45f6-ad39-c9f6795be6f2/msvcrt-iob-disappeared?forum=vclanguage

评论

0赞 Sisir 6/21/2019
以下是对此解决方案的讨论:social.msdn.microsoft.com/Forums/vstudio/en-US/...
-3赞 Deep Patel 4/11/2020 #17

将此代码粘贴到任何源文件中,然后重新生成。 为我工作!

 #include <stdio.h>

FILE _iob[3];

FILE* __cdecl __iob_func(void)
{

   _iob[0] = *stdin;

   _iob[0] = *stdout;

   _iob[0] = *stderr;

   return _iob;

}

评论

0赞 Antonin GAVREL 4/11/2020
您应该添加带有“”的格式以及一些解释
0赞 Brian61354270 4/11/2020
虽然这段代码可能会解决这个问题,但包括解释它如何以及为什么解决这个问题将真正有助于提高你的帖子的质量,并可能导致更多的赞成票。请记住,您是在为将来的读者回答问题,而不仅仅是现在提问的人。请编辑您的答案以添加解释,并指出适用的限制和假设。
0赞 Aeryes 8/30/2020 #18

也许这可能会对你有所帮助。我将 Shell32.lib 添加到我的链接器 --> Input --> Additional Dependencies 中,它阻止了此错误。我从这篇文章中发现了它: https://discourse.libsdl.org/t/windows-build-fails-with-missing-symbol-imp-commandlinetoargvw/27256/3

评论

0赞 HolyBlackCat 8/30/2020
您是否遇到与 OP 或 s 完全相同的错误?unresolved external symbol
0赞 Aeryes 8/30/2020
一般是未解析的外部符号。在我添加shell32.lib之前没有任何效果。我没有意识到这个线程已经有 5 年的历史了......哎呀。
1赞 HolyBlackCat 8/30/2020
一般来说,碰撞旧线程是可以的,但链接可能无法解决 OP 描述的问题(究竟哪个符号是“未解决”很重要)。Shell32.lib
0赞 ali_salha 8/2/2022 #19

当我尝试将 .lib 链接到我的 vs2015 项目时,我遇到了同样的问题(未解决的外部符号 __impl_printf)

唯一对我有用的解决方案是 project->properties->linker->命令行 在附加选项框中添加: legacy_stdio_definitions.lib

0赞 Thomas 6/2/2023 #20

这适用于 Visual-Studio 2017:

#include<corecrt_wstdio.h>
FILE* __cdecl __iob_func(unsigned const id)
{
   return(__acrt_iob_func(id));
}