{"id":5171,"date":"2014-03-30T19:19:58","date_gmt":"2014-03-30T19:19:58","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/embedded-lua-does-not-print-to-allocated-console-collection-of-common-programming-errors\/"},"modified":"2014-03-30T19:19:58","modified_gmt":"2014-03-30T19:19:58","slug":"embedded-lua-does-not-print-to-allocated-console-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/embedded-lua-does-not-print-to-allocated-console-collection-of-common-programming-errors\/","title":{"rendered":"Embedded Lua does not print to allocated console-Collection of common programming errors"},"content":{"rendered":"<p><strong>TL;DR:<\/strong> The program is using more than one version of the C runtime library. Don&#8217;t do that. It always leads to mysterious symptoms from otherwise correct code.<\/p>\n<h2>Background<\/h2>\n<p>On the face of it, the code you present should work. And, if built and linked with care here, I can make it work. For reference, I&#8217;m building with MingW GCC 4.7.2, for 32-bit Windows, on Win7 Pro. But I believe the underlying issue can occur with any compiler targeting Windows.<\/p>\n<p>I&#8217;m going to walk through the process of finding this bug, in the hope that it is helpful to see how I figured this out. But if you are impatient, skip to the end, then come back here to see how I got there.<\/p>\n<h2>Testable Code<\/h2>\n<p>First, I wrapped your code fragment in enough boiler plate to make it compile and run at all:<\/p>\n<pre><code>#include \n#include \n#include \n#include \n\nint main(int argc, char **argv) {\n    AllocConsole();\n    FILE *fp = freopen(\"CONOUT$\", \"w\", stdout); \n    lua_State *L = luaL_newstate();\n    luaL_openlibs(L);\n    if(luaL_dostring(L,\n             \"print 'print works!'\\n\"\n             \"io.write 'io.write works'\"\n            ))\n    {\n    printf(\"%s\\n\", lua_tostring(L, -1));\n    }\n    Sleep(5000); \/\/ give me 5 seconds to read the console\n}\n<\/code><\/pre>\n<h2>Compilation with GCC<\/h2>\n<p>I compiled and linked about as simply as possible on Windows, which isn&#8217;t too bad since I have a copy of Lua for Windows installed which happens to leave the environment variable <code>LUA_DEV<\/code> pointing at its installation:<\/p>\n<pre><code>gcc -o q15787892 q15787892.c -mwindows -I\"%LUA_DEV%\\include\" \"%LUA_DEV%\\lua5.1.dll\"\n<\/code><\/pre>\n<p>The <code>-mwindows<\/code> flag tells GCC (specifically the linker <code>ld<\/code>) to mark the executable as a full Windows GUI program. Without that flag, you get a console program that already has a Console assigned and AllocConsole() will simply provide handles to the one holding the command prompt.<\/p>\n<h2>Results<\/h2>\n<p>Interestingly, neither the call to <code>print()<\/code> nor <code>io.write()<\/code> produced output. I introduced a syntax error in the Lua text and noted that it did output to the console, showing that <code>stdout<\/code> really was redirected correctly.<\/p>\n<p>I added <code>FILE *old=stdout;<\/code> before the call to <code>freopen()<\/code> and <code>printf(\"%p %p %p\", fp, stdout, oldstdout);<\/code> after it. All three pointers were exactly equal, showing that <code>freopen()<\/code> didn&#8217;t do something unusual.<\/p>\n<p>Looking in the sources to Lua 5.1&#8217;s implementation of the <code>print()<\/code> function we find that it simply calls <code>fputs(s,stdout)<\/code>.<\/p>\n<p>So how is it possible that a call to <code>printf()<\/code> from <code>main()<\/code> works, but a similar call using <code>stdout<\/code> fails?<\/p>\n<h2>Solution<\/h2>\n<p>It is possible if <code>stdout<\/code> in <code>main()<\/code> is not the same as <code>stdout<\/code> in <code>luaB_print()<\/code>.<\/p>\n<p>But both are global variables, and the linker is supposed to make them be the same, right?<\/p>\n<p>Well, not necessarily. The global variable <code>stdout<\/code> is part of the C runtime library. If the Lua core is linked to a different C runtime DLL than the program, then it is possible that Lua core and the program are in fact referring to <em>different<\/em> variables named <code>stdout<\/code>.<\/p>\n<p>A quick check with Dependency Walker shows that my test executable was linked against MSVCRT.DLL (the C runtime preferred by MinGW), but the <code>lua5.1.dll<\/code> from Lua for Windows is linked against MSVCR80.DLL (the C runtime from Visual Studio 2005).<\/p>\n<p>This problem is easily resolved. I changed my test case to link against a build of Lua linked against MSVCRT.DLL, and now the original code works as intended. Here&#8217;s the new build steps, now found in a BAT file, and assuming that <code>lua5_1-4_Win32_dll6_lib<\/code> contains the correctly built Lua core:<\/p>\n<pre><code>setlocal\nset LUADIR=\"lua5_1_4_Win32_dll6_lib\"\ngcc -o q15787892 q15787892.c -mwindows -I\"%LUADIR%\\include\" \"%LUADIR%\\lua5.1.dll\"\nif not exist lua5.1.dll copy %LUADIR%\\lua5.1.dll .\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR: The program is using more than one version of the C runtime library. Don&#8217;t do that. It always leads to mysterious symptoms from otherwise correct code. Background On the face of it, the code you present should work. And, if built and linked with care here, I can make it work. For reference, I&#8217;m [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-5171","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/5171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=5171"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/5171\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=5171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=5171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=5171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}