Lazarus

Free Pascal => FPC development => Topic started by: 440bx on March 27, 2019, 08:03:26 pm

Title: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 27, 2019, 08:03:26 pm
Hello,

the following code snippet
Code: Pascal  [Select]
  1.     WM_CREATE:
  2.     begin
  3.     if not AllocConsole then
  4.           begin
  5.             MessageBox(Wnd,
  6.                        'Failed to allocate a console',
  7.                        'AllocConsole error',
  8.                        MB_ICONERROR or MB_OK);
  9.             exit;
  10.           end;
  11.  
  12.  
  13.             writeln('  outputting text now that we have a console is ' +
  14.                     'possible.');
  15.  
  16.  
  17.           exit;
  18.  
  19.       exit;
  20.     end;
  21.  
causes FPC to throw a runtime error at the writeln, Delphi outputs the string to the console without problem.

It seems FPC uses invalid handles for STDOUT (and likely STDIN and STDERR) when the console is allocated instead of created by the FPC RTL.  Adding {$MODE DELPHI} does not solve the problem.

As a workaround to the problem, is there a way to tell FPC what the handles for STDIN, STDOUT and STDERR are once the console has been created/allocated  ?

The attached project which compiles with Delphi 2, Delphi 10 (32 and 64bit) and FPC reproduces the problem.

Thank you for your help.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: ASBzone on March 27, 2019, 08:33:58 pm
I was able to replicate the error in FPC 3.2.0 Fixes / Lazarus 2.0 Fixes

Interestingly, I made the following change and don't get an error. 

Code: Pascal  [Select]
  1.             writeln(stdout,'  outputting text now that we have a console is ' +
  2.                     'possible.');    

 But I also don't get the message in the intended way... :)

Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 27, 2019, 08:49:28 pm
I was able to replicate the error in FPC 3.2.0 Fixes / Lazarus 2.0 Fixes

 But I also don't get the message in the intended way... :)
As you remarked, that is interesting.

As a result, I tried this:
Code: Pascal  [Select]
  1.           OutHandle := GetStdHandle(STD_OUTPUT_HANDLE);
  2.  
  3.             writeln(OutHandle, '  outputting text now that we have a console is ' +
  4.                     'possible.');
  5.  
Unfortunately, that didn't bring any joy.  Worth a try though, chuckle.  I guess it wants a full TextRec not just a handle.

Title: Re: FPC throws a runtime error with working Delphi code
Post by: marcov on March 27, 2019, 09:15:55 pm
The help of allocconsole (https://docs.microsoft.com/en-us/windows/console/allocconsole) says you need to load the handles using getstdhandle.

So the Delphi case seems to depend on coincidental equal values of handles. IOW, that piece of code is buggy.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: Cyrax on March 27, 2019, 09:16:53 pm
You need to call System.SysInitStdIO to initialize several variables related to console functionality in the RTL.

EDIT : Apparently you need to set System.IsConsole to True before you call System.SysInitStdIO, too.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 27, 2019, 09:27:54 pm
The help of allocconsole (https://docs.microsoft.com/en-us/windows/console/allocconsole) says you need to load the handles using getstdhandle.
Of course but, that is applicable when using other Windows console APIs, not writeln.  writeln is supposed to get the handle itself - possibly using GetStdHandle(STD_OUTPUT_HANDLE) - the problem seems to be that FPC only initializes the console related handles at startup instead of refreshing them at runtime (necessary for GUI apps, since those can allocate and free consoles at will, as Delphi seems to know.)

You need to call System.SysInitStdIO to initialize several variables related to console functionality in the RTL.
I put that call just before the writeln and I still get a runtime error. Is there something else I have to do for FPC to update its internal console handles ?
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 27, 2019, 09:58:20 pm
EDIT : Apparently you need to set System.IsConsole to True before you call System.SysInitStdIO, too.
That got rid of the runtime exception, that's an improvement :)  but writeln didn't output the string it was supposed to. 
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 27, 2019, 10:23:49 pm
So the Delphi case seems to depend on coincidental equal values of handles. IOW, that piece of code is buggy.
It's rather unlikely that the same "bug" exists in Delphi 2 all the way to Delphi 10 and even more unlikely would be that a random (not initialized) value happens to be a correct handle _every_ time.

It's neither a bug nor a coincidence, Delphi checks the console handles at runtime and initializes them when a GUI app allocates a console as the following Delphi code shows:
Code: Pascal  [Select]
  1. // delphi executes this when it finds there is a new console
  2.  
  3. TextOpen:
  4. 0000000000403DA0 55               push rbp
  5. 0000000000403DA1 56               push rsi
  6. 0000000000403DA2 53               push rbx
  7. 0000000000403DA3 4883EC50         sub rsp,$50
  8. 0000000000403DA7 488BEC           mov rbp,rsp
  9. 0000000000403DAA 4889CB           mov rbx,rcx
  10. 0000000000403DAD 4833F6           xor rsi,rsi
  11. 0000000000403DB0 C7431000000000   mov [rbx+$10],$00000000
  12. 0000000000403DB7 C7431400000000   mov [rbx+$14],$00000000
  13. 0000000000403DBE 480FB74308       movzx rax,word ptr [rbx+$08]
  14. 0000000000403DC3 6681E8B1D7       sub ax,$d7b1
  15. 0000000000403DC8 6685C0           test ax,ax
  16. 0000000000403DCB 7418             jz TextOpen + $45
  17. 0000000000403DCD 6683E801         sub ax,$01
  18. 0000000000403DD1 6685C0           test ax,ax
  19. 0000000000403DD4 7428             jz TextOpen + $5E
  20. 0000000000403DD6 6683E801         sub ax,$01
  21. 0000000000403DDA 6685C0           test ax,ax
  22. 0000000000403DDD 0F85B5020000     jnz TextOpen + $2F8
  23. 0000000000403DE3 EB32             jmp TextOpen + $77
  24. 0000000000403DE5 C7C000000080     mov eax,$80000000
  25. 0000000000403DEB C7C103000000     mov ecx,$00000003
  26. 0000000000403DF1 488D1578FEFFFF   lea rdx,[rel $fffffe78]
  27. 0000000000403DF8 48895328         mov [rbx+$28],rdx
  28. 0000000000403DFC EB30             jmp TextOpen + $8E
  29. 0000000000403DFE C7C000000040     mov eax,$40000000
  30. 0000000000403E04 C7C102000000     mov ecx,$00000002
  31. 0000000000403E0A 488D15BFFEFFFF   lea rdx,[rel $fffffebf]
  32. 0000000000403E11 48895328         mov [rbx+$28],rdx
  33. 0000000000403E15 EB17             jmp TextOpen + $8E
  34. 0000000000403E17 C7C0000000C0     mov eax,$c0000000
  35. 0000000000403E1D C7C103000000     mov ecx,$00000003
  36. 0000000000403E23 488D15A6FEFFFF   lea rdx,[rel $fffffea6]
  37. 0000000000403E2A 48895328         mov [rbx+$28],rdx
  38. 0000000000403E2E 488D158BFEFFFF   lea rdx,[rel $fffffe8b]
  39. 0000000000403E35 48895330         mov [rbx+$30],rdx
  40. 0000000000403E39 66837B6000       cmp word ptr [rbx+$60],$00
  41. 0000000000403E3E 0F85B9000000     jnz TextOpen + $15D
  42. 0000000000403E44 48837B1800       cmp qword ptr [rbx+$18],$00
  43. 0000000000403E49 7512             jnz TextOpen + $BD
  44. 0000000000403E4B 488D8368020000   lea rax,[rbx+$00000268]
  45. 0000000000403E52 48894318         mov [rbx+$18],rax
  46. 0000000000403E56 C7430C80000000   mov [rbx+$0c],$00000080
  47. 0000000000403E5D 488D055CFEFFFF   lea rax,[rel $fffffe5c]
  48. 0000000000403E64 48894338         mov [rbx+$38],rax
  49. 0000000000403E68 66817B08B2D7     cmp word ptr [rbx+$08],$d7b2
  50. 0000000000403E6E 7526             jnz TextOpen + $F6
  51. 0000000000403E70 488D0501A80000   lea rax,[rel $0000a801]
  52. 0000000000403E77 483BD8           cmp rbx,rax
  53. 0000000000403E7A 7508             jnz TextOpen + $E4
  54. 0000000000403E7C C7C0F4FFFFFF     mov eax,$fffffff4
  55. 0000000000403E82 EB06             jmp TextOpen + $EA
  56. 0000000000403E84 C7C0F5FFFFFF     mov eax,$fffffff5
  57. 0000000000403E8A 89C1             mov ecx,eax
  58. 0000000000403E8C E87FD1FFFF       call GetStdHandle
  59. 0000000000403E91 488903           mov [rbx],rax
  60. 0000000000403E94 EB0E             jmp TextOpen + $104
  61. 0000000000403E96 C7C1F6FFFFFF     mov ecx,$fffffff6
  62.  
  63. // GetStdHandle to get the handle
  64.  
  65. 0000000000403E9C E86FD1FFFF       call GetStdHandle
  66. 0000000000403EA1 488903           mov [rbx],rax
  67. 0000000000403EA4 6683BBE802000000 cmp word ptr [rbx+$000002e8],$00
  68. 0000000000403EAC 0F85AA010000     jnz TextOpen + $2BC
  69. 0000000000403EB2 488B0B           mov rcx,[rbx]
  70.  
  71. // determine the file type
  72.  
  73. 0000000000403EB5 E886D1FFFF       call GetFileType
  74. 0000000000403EBA 83F802           cmp eax,$02
  75. 0000000000403EBD 752A             jnz TextOpen + $149
  76. 0000000000403EBF 66817B08B2D7     cmp word ptr [rbx+$08],$d7b2
  77. 0000000000403EC5 7511             jnz TextOpen + $138
  78. 0000000000403EC7 E8C4D2FFFF       call GetConsoleOutputCP
  79. 0000000000403ECC 668983E8020000   mov [rbx+$000002e8],ax
  80. 0000000000403ED3 E984010000       jmp TextOpen + $2BC
  81.  
  82. // and the code page
  83.  
  84. 0000000000403ED8 E8A3D2FFFF       call GetConsoleCP
  85.  
  86. // etc
  87.  
  88. 0000000000403EDD 668983E8020000   mov [rbx+$000002e8],ax
  89. 0000000000403EE4 E973010000       jmp TextOpen + $2BC
  90. 0000000000403EE9 480FB7057BAA0000 movzx rax,word ptr [rel $0000aa7b]
  91. 0000000000403EF1 668983E8020000   mov [rbx+$000002e8],ax
  92. 0000000000403EF8 E95F010000       jmp TextOpen + $2BC
  93. 0000000000403EFD 488D153CFEFFFF   lea rdx,[rel $fffffe3c]
  94. 0000000000403F04 48895338         mov [rbx+$38],rdx
  95. 0000000000403F08 488D5360         lea rdx,[rbx+$60]
  96. 0000000000403F0C 41C7C001000000   mov r8d,$00000001
  97. 0000000000403F13 4D33C9           xor r9,r9
  98. 0000000000403F16 894C2420         mov [rsp+$20],ecx
  99. 0000000000403F1A C744242880000000 mov [rsp+$28],$00000080
  100. 0000000000403F22 48C744243000000000 mov qword ptr [rsp+$30],$0000000000000000
  101. 0000000000403F2B 4889D1           mov rcx,rdx
  102. 0000000000403F2E 89C2             mov edx,eax
  103. 0000000000403F30 E8EBD0FFFF       call CreateFile
  104. 0000000000403F35 4883F8FF         cmp rax,-$01
  105. 0000000000403F39 7512             jnz TextOpen + $1AD
  106. 0000000000403F3B 66C74308B0D7     mov word ptr [rbx+$08],$d7b0
  107. 0000000000403F41 E8CAD1FFFF       call GetLastError
  108. 0000000000403F46 89C6             mov esi,eax
  109. 0000000000403F48 E94B010000       jmp TextOpen + $2F8
  110. 0000000000403F4D 488903           mov [rbx],rax
  111. 0000000000403F50 66817B08B3D7     cmp word ptr [rbx+$08],$d7b3
  112. 0000000000403F56 0F85E7000000     jnz TextOpen + $2A3
  113. 0000000000403F5C 66C74308B2D7     mov word ptr [rbx+$08],$d7b2
  114. 0000000000403F62 488B0B           mov rcx,[rbx]
  115. 0000000000403F65 4833D2           xor rdx,rdx
  116. 0000000000403F68 E8C3D0FFFF       call GetFileSize
  117. 0000000000403F6D 83F8FF           cmp eax,-$01
  118. 0000000000403F70 750F             jnz TextOpen + $1E1
  119. 0000000000403F72 4889D9           mov rcx,rbx
  120. 0000000000403F75 E8F6FDFFFF       call TextOpenCleanup
  121. 0000000000403F7A 89C6             mov esi,eax
  122. 0000000000403F7C E917010000       jmp TextOpen + $2F8
  123. 0000000000403F81 81E880000000     sub eax,$00000080
  124. 0000000000403F87 85C0             test eax,eax
  125. 0000000000403F89 7D03             jnl TextOpen + $1EE
  126. 0000000000403F8B 4833C0           xor rax,rax
  127. 0000000000403F8E 488B0B           mov rcx,[rbx]
  128. 0000000000403F91 89C2             mov edx,eax
  129. 0000000000403F93 4D33C0           xor r8,r8
  130. 0000000000403F96 4D33C9           xor r9,r9
  131. 0000000000403F99 E8D2D0FFFF       call SetFilePointer
  132. 0000000000403F9E 83F8FF           cmp eax,-$01
  133. 0000000000403FA1 7427             jz TextOpen + $22A
  134. 0000000000403FA3 488B0B           mov rcx,[rbx]
  135. 0000000000403FA6 488D9368020000   lea rdx,[rbx+$00000268]
  136. 0000000000403FAD 41C7C080000000   mov r8d,$00000080
  137. 0000000000403FB4 4C8D4D4C         lea r9,[rbp+$4c]
  138. 0000000000403FB8 48C744242000000000 mov qword ptr [rsp+$20],$0000000000000000
  139. 0000000000403FC1 E88AD0FFFF       call ReadFile
  140. 0000000000403FC6 85C0             test eax,eax
  141. 0000000000403FC8 750F             jnz TextOpen + $239
  142. 0000000000403FCA 4889D9           mov rcx,rbx
  143. 0000000000403FCD E89EFDFFFF       call TextOpenCleanup
  144. 0000000000403FD2 89C6             mov esi,eax
  145. 0000000000403FD4 E9BF000000       jmp TextOpen + $2F8
  146. 0000000000403FD9 480FB7430A       movzx rax,word ptr [rbx+$0a]
  147. 0000000000403FDE 66F7C00100       test ax,$0001
  148. 0000000000403FE3 745E             jz TextOpen + $2A3
  149. 0000000000403FE5 837D4C00         cmp dword ptr [rbp+$4c],$00
  150. 0000000000403FE9 7658             jbe TextOpen + $2A3
  151. 0000000000403FEB 4833C0           xor rax,rax
  152. 0000000000403FEE 8B4D4C           mov ecx,[rbp+$4c]
  153. 0000000000403FF1 83E901           sub ecx,$01
  154. 0000000000403FF4 3BC1             cmp eax,ecx
  155. 0000000000403FF6 774A             jnbe TextOpen + $2A2
  156. 0000000000403FF8 83C101           add ecx,$01
  157. 0000000000403FFB 8BD0             mov edx,eax
  158. 0000000000403FFD 80BC13680200001A cmp byte ptr [rbx+rdx+$0268],$1a
  159. 0000000000404005 7534             jnz TextOpen + $29B
  160. 0000000000404007 488B0B           mov rcx,[rbx]
  161. 000000000040400A 8BD0             mov edx,eax
  162. 000000000040400C 2B554C           sub edx,[rbp+$4c]
  163. 000000000040400F 4D33C0           xor r8,r8
  164. 0000000000404012 41C7C102000000   mov r9d,$00000002
  165. 0000000000404019 E852D0FFFF       call SetFilePointer
  166. 000000000040401E 83F8FF           cmp eax,-$01
  167. 0000000000404021 740C             jz TextOpen + $28F
  168. 0000000000404023 488B0B           mov rcx,[rbx]
  169. 0000000000404026 E835D0FFFF       call SetEndOfFile
  170. 000000000040402B 85C0             test eax,eax
  171. 000000000040402D 7513             jnz TextOpen + $2A2
  172. 000000000040402F 4889D9           mov rcx,rbx
  173. 0000000000404032 E839FDFFFF       call TextOpenCleanup
  174. 0000000000404037 89C6             mov esi,eax
  175. 0000000000404039 EB5D             jmp TextOpen + $2F8
  176. 000000000040403B 83C001           add eax,$01
  177. 000000000040403E 3BC1             cmp eax,ecx
  178. 0000000000404040 75B9             jnz TextOpen + $25B
  179. 0000000000404042 90               nop
  180. 0000000000404043 6683BBE802000000 cmp word ptr [rbx+$000002e8],$00
  181. 000000000040404B 750F             jnz TextOpen + $2BC
  182. 000000000040404D 480FB70517A90000 movzx rax,word ptr [rel $0000a917]
  183. 0000000000404055 668983E8020000   mov [rbx+$000002e8],ax
  184. 000000000040405C 66817B08B1D7     cmp word ptr [rbx+$08],$d7b1
  185. 0000000000404062 7434             jz TextOpen + $2F8
  186. 0000000000404064 488B0B           mov rcx,[rbx]
  187. 0000000000404067 E8D4CFFFFF       call GetFileType
  188. 000000000040406C 83E801           sub eax,$01
  189. 000000000040406F 83F8FF           cmp eax,-$01
  190. 0000000000404072 7409             jz TextOpen + $2DD
  191. 0000000000404074 83E801           sub eax,$01
  192. 0000000000404077 85C0             test eax,eax
  193. 0000000000404079 751D             jnz TextOpen + $2F8
  194. 000000000040407B EB10             jmp TextOpen + $2ED
  195. 000000000040407D 4889D9           mov rcx,rbx
  196. 0000000000404080 E8EBFCFFFF       call TextOpenCleanup
  197. 0000000000404085 C7C669000000     mov esi,$00000069
  198. 000000000040408B EB0B             jmp TextOpen + $2F8
  199. 000000000040408D 488D053CFCFFFF   lea rax,[rel $fffffc3c]
  200. 0000000000404094 48894330         mov [rbx+$30],rax
  201. 0000000000404098 89F0             mov eax,esi
  202. 000000000040409A 488D6550         lea rsp,[rbp+$50]
  203. 000000000040409E 5B               pop rbx
  204. 000000000040409F 5E               pop rsi
  205. 00000000004040A0 5D               pop rbp
  206. 00000000004040A1 C3               ret
  207.  
  208. // return to the writeln routines with valid console handles
  209.  

Definitely not a bug nor coincidence. 
Title: Re: FPC throws a runtime error with working Delphi code
Post by: Akira1364 on March 27, 2019, 10:25:44 pm
What you actually need to do is:

- not have {$APPTYPE GUI} in there at all
- not set IsConsole to true (because it already is then), and not call SysInitStdIO (again, unnecessary)
- get rid of the AllocConsole call completely (you don't need it as you'll already have one)

The program then works as it seems to be intended to (as FPC's console handling and your direct WinAPI calls for the GUI don't directly conflict with each other unless you overlap them)
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 27, 2019, 10:37:59 pm
What you actually need to do is:

- not have {$APPTYPE GUI} in there at all
- not set IsConsole to true (because it already is then), and not call SysInitStdIO (again, unnecessary)
- get rid of the AllocConsole call completely (you don't need it as you'll already have one)

The program then works as it seems to be intended to (as FPC's console handling and your direct WinAPI calls for the GUI don't directly conflict with each other unless you overlap them)
The app is a GUI app that allocates a console whenever it needs one and frees it when it no longer needs it.  This can happen multiple times.  The consoles (one at a time, of course) are simply a "convenience" nothing else, it is not the app.

But, thank you for the suggestion. I appreciate it.

Anyway, it seems FPC should handle runtime allocated consoles correctly and not simply assume that a console is not created at runtime by a GUI app.

A way to give the FPC RTL the necessary information for it to use the allocated console would solve the problem.

Title: Re: FPC throws a runtime error with working Delphi code
Post by: ASBzone on March 27, 2019, 10:43:07 pm
What you actually need to do is:- not have {$APPTYPE GUI} in there at all- not set IsConsole to true (because it already is then), and not call SysInitStdIO (again, unnecessary)- get rid of the AllocConsole call completely (you don't need it as you'll already have one)The program then works as it seems to be intended to (as FPC's console handling and your direct WinAPI calls for the GUI don't directly conflict with each other unless you overlap them)



But what if the goal is to have a GUI application that manages and writes something to a console? (in addition to whatever else it is doing)
Title: Re: FPC throws a runtime error with working Delphi code
Post by: Akira1364 on March 27, 2019, 10:53:48 pm
But what if the goal is to have a GUI application that manages and writes something to a console? (in addition to whatever else it is doing)[/font]

Well, the suggestion I made does allow exactly what you're describing. It does not account for creating and destroying multiple consoles, though.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: ASBzone on March 27, 2019, 11:25:07 pm
But what if the goal is to have a GUI application that manages and writes something to a console? (in addition to whatever else it is doing)

Well, the suggestion I made does allow exactly what you're describing. It does not account for creating and destroying multiple consoles, though.

I see that now, thanks.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: Akira1364 on March 27, 2019, 11:49:38 pm
I took another look, and it works with {$APPTYPE GUI} if the program begins like this:

Code: Pascal  [Select]
  1. begin
  2.   AllocConsole;
  3.   IsConsole := True;
  4.   SysInitStdIO;
  5.   WinMain;
  6. end.

With no call to AllocConsole in WndProc. I'm not sure what would happen if you destroyed that initial console and created a new one, though.

AFAIK WriteLn is not exactly designed (in FPC) to be used in conjunction with arbitrary non-portable-API calls, however... might be better to use the Windows console API directly as well.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 28, 2019, 01:30:35 am
I took another look, and it works with {$APPTYPE GUI} if the program begins like this:

Code: Pascal  [Select]
  1. begin
  2.   AllocConsole;
  3.   IsConsole := True;
  4.   SysInitStdIO;
  5.   WinMain;
  6. end.

With no call to AllocConsole in WndProc. I'm not sure what would happen if you destroyed that initial console and created a new one, though.

AFAIK WriteLn is not exactly designed (in FPC) to be used in conjunction with arbitrary non-portable-API calls, however... might be better to use the Windows console API directly as well.
Thank you for looking further into it.

The problem is writeln is assuming that once a console exists it is "here to stay" when, in reality, consoles can come and go just as memory blocks do (allocate them, use them, free them, just like anything else.)

It would be more than just nice if there was a way to notify the RTL a console has been created (at anytime) so it can setup its internal structures for console I/O and a function to let it know the console has been freed/destroyed so it can do any necessary cleanup.  That would be a reasonable and practical way of solving the problem. Delphi figures it out on the fly which is more overhead but.... got to say, that is nice (correct is always nice :))

Title: Re: FPC throws a runtime error with working Delphi code
Post by: engkin on March 28, 2019, 01:45:58 am
It seems to me it is possible to create and destroy consoles building on Akira's code:
Code: Pascal  [Select]
  1. function fpAllocConsole: boolean;
  2. begin
  3.   Result := AllocConsole;
  4.   {$ifdef FPC}
  5.   if Result then
  6.   begin
  7.     IsConsole := True;
  8.     SysInitStdIO;
  9.   end;
  10.   {$endif FPC}
  11. end;

Changing your code to test:
Code: Pascal  [Select]
  1.   case Msg of
  2.     WM_CREATE:
  3.     begin
  4.     if not fpAllocConsole then
  5.           begin
  6.             MessageBox(Wnd,
  7.                        'Failed to allocate a console',
  8.                        'AllocConsole error',
  9.                        MB_ICONERROR or MB_OK);
  10.             exit;
  11.           end;
  12.  
  13.             writeln(Output, '1  outputting text now that we have a console is ' +
  14.                     'possible.');
  15.             ReadLn;
  16.             FreeConsole;
  17.  
  18.             fpAllocConsole;
  19.             writeln(Output, '2  outputting text now that we have a console is ' +
  20.                     'possible.');
  21.             ReadLn;
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 28, 2019, 04:11:32 am
@Engkin:

I tried what you and Akira suggested and didn't get any output from writeln, not even on the first console allocation.




Title: Re: FPC throws a runtime error with working Delphi code
Post by: ASerge on March 28, 2019, 05:12:38 pm
Code: Pascal  [Select]
  1. ...
  2. uses Windows;
  3.  
  4. function InitConsole: Boolean;
  5. begin
  6.   Result := AllocConsole;
  7.   if not Result then
  8.     Exit;
  9.   StdInputHandle := 0;
  10.   StdOutputHandle := 0;
  11.   StdErrorHandle := 0;
  12.   IsConsole := True;
  13.   SysInitStdIO;
  14.   IsConsole := False;
  15. end;
  16.  
  17. procedure DoneConsole;
  18. begin
  19.   SysFlushStdIO;
  20.   FreeConsole;
  21.   SysInitStdIO;
  22. end;
  23.  
  24. procedure TForm1.Button1Click(Sender: TObject);
  25. begin
  26.   if InitConsole then
  27.   try
  28.     Writeln('OK');
  29.     Readln;
  30.   finally
  31.     DoneConsole;
  32.   end;
  33. end;
Title: Re: FPC throws a runtime error with working Delphi code
Post by: ASBzone on March 28, 2019, 07:59:37 pm
@Engkin: I tried what you and Akira suggested and didn't get any output from writeln, not even on the first console allocation.
What Akiira provided (yesterday) worked for me.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: Thaddy on March 28, 2019, 08:10:08 pm
What Akiira provided (yesterday) worked for me.
The code by ASerge is more complete. I suggest you use that.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: engkin on March 28, 2019, 08:49:53 pm
@Engkin:

I tried what you and Akira suggested and didn't get any output from writeln, not even on the first console allocation.

You are right, you are running the code under Lazarus. Can you try again with this:
Code: Pascal  [Select]
  1. function fpAllocConsole: boolean;
  2. begin
  3.   Result := AllocConsole;
  4.   {$ifdef FPC}
  5.   if Result then
  6.   begin
  7.     IsConsole := True;
  8.     StdInputHandle  := 0;
  9.     StdOutputHandle := 0;
  10.     StdErrorHandle  := 0;
  11.     SysInitStdIO;
  12.   end;
  13.   {$endif FPC}
  14. end;

Edit:
ASerge figured it before I did.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: Thaddy on March 28, 2019, 09:42:59 pm
Yes. and all such things should go in the wiki. I'll see if I have time, otherwise feel free to add it  yourself.
Title: Re: FPC throws a runtime error with working Delphi code
Post by: 440bx on March 29, 2019, 12:49:07 am
@Akira, @Engkin and @Serge

A heartfelt thank you to the three of you for your efforts to solve the problem.  This solution saves me a lot of time and hassle. :)

Engkin, Serge... my hat off to you guys.  I owe you one.

For anyone who might benefit from seeing "applicability", I attached a small program that works with Delphi 2, Delphi 10 and FPC in 32 and 64bit.