Author Topic: Compliant 64-bit compiling  (Read 8690 times)

0 Members and 1 Guest are viewing this topic.

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4416
    • Oxygen Basic
Re: Compliant 64-bit compiling
« Reply #30 on: December 13, 2019, 05:10:47 AM »
Hi Roland,

Yes, end extern is normally inserted after external declarations, and all functions and their declarations are considered 'internal' by default until the next 'extern' statement.

extern statement direct the compiler to use standard (DLL) calling conventions instead of the more efficient internal calling conventions.

Individual procedures are also made 'extern' by any of the following tags:
external extern callback export
« Last Edit: December 13, 2019, 05:25:24 AM by Charles Pegge »

Arnold

  • Hero Member
  • *****
  • Posts: 973
Re: Compliant 64-bit compiling
« Reply #31 on: December 15, 2019, 05:42:42 AM »
Hi Charles,

I found this code in /inc/crt/win32/stdio.bi of Freebasic v.1.07.1 and it makes me crazy:

...
#ifdef __FB_64BIT__
   declare function __iob_func() as FILE ptr
   #define stdin (@(__iob_func())[STDIN_FILENO])
   #define stdout (@(__iob_func())[STDOUT_FILENO])
   #define stderr (@(__iob_func())[STDERR_FILENO])
#else
   extern import _iob(0 to 2) alias "_iob" as FILE
   #define stdin (@_iob(STDIN_FILENO))
   #define stdout (@_iob(STDOUT_FILENO))
   #define stderr (@_iob(STDERR_FILENO))
#endif
...

I tried to port this to Oxygen but obviously I do it the wrong way:

Code: [Select]
$ Filename "Test_iob.exe"
'uses rtl32
'uses rtl64

uses corewin
uses console

indexbase 0

% STDIN_FILENO 0
% STDOUT_FILENO 1
% STDERR_FILENO 2

#ifndef mode64bit
//  extern import _iob(0 to 2) alias "_iob" as FILE
sys _iob = __p__iob()
sys stdin  = @_iob(STDIN_FILENO)
sys stdout = @_iob(STDOUT_FILENO)
sys stderr = @_iob(STDERR_FILENO)
#else
// declare function __iob_func() as FILE ptr
//    #define stdin  (@(__iob_func())[STDIN_FILENO])
//    #define stdout (@(__iob_func())[STDOUT_FILENO])
//    #define stderr (@(__iob_func())[STDERR_FILENO])
sys stdin  = call @__iob_func[STDIN_FILENO]
sys stdout = call @__iob_func[STDOUT_FILENO]
sys stderr = call @__iob_func[STDERR_FILENO]
#endif

printl stdin
printl stdout
printl stderr

printl "Enter"
waitkey

For 32-bit this will work but 64-bit crashes. I think I must do it similar like it was done using dispatch_table in o2scm.o2bas or was done in the demo \examples\Basics\FuncPointers1.o2bas. Although I tried some alternatives, somehow I cannot get any further. My logic is wrong and it seems that I am not flexible enough. Can you help?

Roland

Arnold

  • Hero Member
  • *****
  • Posts: 973
Re: Compliant 64-bit compiling
« Reply #32 on: December 15, 2019, 01:14:14 PM »
This will run in 32-bit and 64-bit mode, but probably there is a better solution:

Code: [Select]
$ Filename "Test_printf.exe"
'uses rtl32
'uses rtl64

uses corewin
uses console

indexbase 0

extern
! printf (char* a, ...) at @printf

% STDIN_FILENO 0
% STDOUT_FILENO 1
% STDERR_FILENO 2

type FILE
char* _ptr
int _cnt
char* _base
int _flag
int _file
int _charbuf
int _bufsiz
char* _tmpfname
end type

#define _O_TEXT 0x4000 // CRLF in file becomes LF in memory!
#define _IONBF  0x4

#ifndef mode64bit
//  extern import _iob(0 to 2) alias "_iob" as FILE
FILE* _iob = __p__iob()
sys stdin  = @_iob(STDIN_FILENO)
sys stdout = @_iob(STDOUT_FILENO)
sys stderr = @_iob(STDERR_FILENO)
#else
// declare function __iob_func() as FILE ptr
sys stdin  = call @__iob_func()
sys stdout = stdin + sizeof(FILE)
sys stderr = stdout + sizeof(FILE)
#endif

'printl stdin
'printl stdout
'printl stderr + cr

sys hCrt = _open_osfhandle(ConsOut, _O_TEXT)
sys hf   = _fdopen(hCrt, "w")
memcpy  stdout, hf, sizeof(FILE)
setvbuf stdout, NULL, _IONBF, 0

fprintf(stdout, "loading %s" + chr(10), "Testfile.txt")
fprintf(stdout, "Oxygen ")
printf (chr(10) + "OxygenBasic")

printl "Enter"
waitkey

It should be possible to create a __iob_func() table, but I do not know how this can be done.

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 4416
    • Oxygen Basic
Re: Compliant 64-bit compiling
« Reply #33 on: December 16, 2019, 05:33:19 AM »
Hi Roland,

This works for 64bit:

Code: [Select]
#ifndef mode64bit
//  extern import _iob(0 to 2) alias "_iob" as FILE
FILE* _iob = __p__iob()
sys stdin  = @_iob(STDIN_FILENO)
sys stdout = @_iob(STDOUT_FILENO)
sys stderr = @_iob(STDERR_FILENO)
#else
// declare function __iob_func() as FILE ptr
FILE* _iob = __iob_func()
sys stdin  = @_iob(STDIN_FILENO)
sys stdout = @_iob(STDOUT_FILENO)
sys stderr = @_iob(STDERR_FILENO)
'sys stdin  = __iob_func()
'sys stdout = stdin + sizeof(FILE)
'sys stderr = stdout + sizeof(FILE)
#endif

Mike Lobanovsky

  • Hero Member
  • *****
  • Posts: 1993
Re: Compliant 64-bit compiling
« Reply #34 on: December 16, 2019, 08:47:57 AM »
... or this: ;)

Code: [Select]
#ifndef mode64bit
FILE* _iob = __p__iob()
#else
FILE* _iob = __iob_func()
#endif

sys stdin  = @_iob(STDIN_FILENO)
sys stdout = @_iob(STDOUT_FILENO)
sys stderr = @_iob(STDERR_FILENO)
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)

Arnold

  • Hero Member
  • *****
  • Posts: 973
Re: Compliant 64-bit compiling
« Reply #35 on: December 17, 2019, 02:05:04 AM »
Many thanks. This is far better than my trial and error and will help to understand simiiar constructs. And I now can see that the procedure was already described in /Console/Printf.o2bas. I adapted Printf.o2bas a bit and it runs fine in 32-bit and 64-bit:

Code: OxygenBasic
  1. $filename "printf.exe"
  2. 'uses rtl32
  3. 'uses rtl64
  4.  
  5. 'Getting printf to operate in JIT mode
  6. ======================================
  7.  
  8. 'Thanks to Mike Lobanovsky
  9. '12:28 07/10/2014
  10.  
  11. #console
  12. '%NoConsole
  13. %TryAttachConsole
  14.  
  15. uses corewin
  16. uses console
  17.  
  18. indexbase 0
  19.  
  20. ' _iob[FOPEN_MAX] is msvcrt's internal file buffer array.
  21. ' _iob[] can be exported directly, or via cdecl __p__iob(), or via cdecl __iob_func().
  22. ' Reference:
  23. ' #define FOPEN_MAX     20
  24. ' #define STDIN_FILENO  0
  25. ' #define STDOUT_FILENO 1
  26. ' #define STDERR_FILENO 2
  27. ' #define stdin         &_iob[STDIN_FILENO]
  28. ' #define stdout        &_iob[STDOUT_FILENO]
  29. ' #define stderr        &_iob[STDERR_FILENO]
  30.  
  31. % STDIN_FILENO 0
  32. % STDOUT_FILENO 1
  33. % STDERR_FILENO 2
  34.  
  35.  
  36. type FILE
  37.         char* _ptr
  38.         int       _cnt
  39.         char* _base
  40.         int       _flag
  41.         int       _file
  42.         int       _charbuf
  43.         int       _bufsiz
  44.         char* _tmpfname
  45. end type
  46.  
  47. /*
  48. extern cdecl lib "msvcrt.dll"
  49. ! __p__iob        () as sys
  50. ! _open_osfhandle (sys a, b) as sys
  51. ! _fdopen         (sys a, char* b) as sys
  52. ! setvbuf         (sys a, char* b, sys c, d)
  53. ! fprintf         '(sys a, char* b, ...)
  54. ! printf          '(char* a, ...)
  55. ! memcpy          (sys a, b, c)
  56. end extern
  57. */
  58.  
  59. #define _O_TEXT 0x4000 // CRLF in file becomes LF in memory!
  60. #define _IONBF  0x4
  61.  
  62. ' same for ConsIn/"r", ConsErr/"w"
  63. sys hCrt = _open_osfhandle(ConsOut, _O_TEXT)
  64. sys hf   = _fdopen(hCrt, "w")
  65.  
  66. ' user-defined buffer (for fprintf() only!)
  67. FILE mystdout at hf
  68. setvbuf @mystdout, NULL, _IONBF, 0
  69.  
  70. ' _iob's internals:
  71. ' stdin at _iob as "r",
  72. ' stdout at iob+sizeof(FILE) as "w"
  73. ' stderr at _iob+2*sizeof(FILE) as "w"
  74. 'sys _iob = __p__iob()
  75. #ifndef mode64bit
  76. FILE* _iob = __p__iob()
  77. #else
  78. FILE* _iob = __iob_func()
  79. #endif
  80.  
  81. sys stdin  = @_iob(STDIN_FILENO)
  82. sys stdout = @_iob(STDOUT_FILENO)
  83. sys stderr = @_iob(STDERR_FILENO)
  84.  
  85. memcpy stdout, hf, sizeof(FILE)
  86. setvbuf stdout, NULL, _IONBF, 0
  87.  
  88. % lf = chr(10)
  89.  
  90. fprintf @mystdout, "fprintf via mystdout: %s and his %s%d" + lf, "Charles", "O", 2
  91. fprintf stdout, "fprintf via stdout  : %s and his %s%d" + lf, "Charles", "O", 2
  92. printf "printf  via stdout  : %s and his %s%d" + lf, "Charles", "O", 2
  93.  
  94. waitkey
  95.  

I guess that as long as msvcrt.dll is supported, there will be many useful additional functions available which help in programming.
« Last Edit: December 17, 2019, 02:15:31 AM by Arnold »

Mike Lobanovsky

  • Hero Member
  • *****
  • Posts: 1993
Re: Compliant 64-bit compiling
« Reply #36 on: December 18, 2019, 04:06:35 AM »
I guess msvcrt.dll, the oldest one, will be supported forever as there are millions of apps linked against that runtime. Conversely, later incarnations are bound to specific MS VC builds/versions and live only as long as those versions are in use until superseded.
Mike
(3.6GHz Intel Core i5 Quad w/ 16GB RAM, nVidia GTX 1060Ti w/ 6GB VRAM, Windows 7 Ultimate Sp1)