Page 1 of 1

to any C guru pls help

Posted: Mon Sep 27, 2004 11:31 am
by gkaizer
i'm trying to port a fprintf function to windows, but no way
this is the code

Code: Select all

Procedure main()
  memo.MEMORY_BASIC_INFORMATION
  ; *pointer = iob()
  ; Debug Hex(*pointer)
  ;fprintf(*pointer +2,"errore!")
  hInst.l = Loadlibrary_("msvcrt.dll")
  If hInst
    *pointer = GetProcAddress_(hInst,"__iob_func"); this returns a pointer
to an array of type FILE
    *fpr = GetProcAddress_(hInst,"fprintf")
    If *pointer
      *deb.l = CallCFunctionFast(*pointer)
      If VirtualQuery_(*deb,@memo,SizeOf(memo))
        Debug memo\State ; = MEM_COMMIT, we can use this memory
      EndIf
      ret.l = CallCFunctionFast(*fpr,@*deb + 2,"errore!") ;@*deb+2 should be stderr see below
      Debug Hex(*deb)
      Debug Hex(*fpr)
    EndIf
  EndIf
  FreeLibrary_(hInst)
EndProcedure

main()

End
from stdio.h

Code: Select all

 typedef struct _iobuf {
       int  cnt;       /* characters left */
       char *ptr;      /* next character position */
       char *base;     /* location of buffer */
       int  flag;      /* mode of file access */
       int  fd;        /* file descriptor */
   } FILE;
   extern FILE _iob[]; 

   #define stdin   (&_iob[0])
   #define stdout  (&_iob[1])
   #define stderr  (&_iob[2])
so, to PureBasic i'll port that snippet like that

Code: Select all

Structure FILE
cnt.l
ptr.l
base.l
flag.l
fd.l
EndStructure

*stderr.l = @*deb + 2 
right?
No, it crashes...any ideas?

PS:i already know there's a method of writing to stderr with windows apis, but that is not definitely what i want.

Posted: Mon Sep 27, 2004 1:05 pm
by Dare2
I think c data types are as follows:

Code: Select all

            short int    2 bytes
   unsigned short int    2 bytes
         unsigned int    4  bytes
                  int    4  bytes
             long int    4  bytes
          signed char    1  byte
        unsigned char    1  byte
                float    4  bytes
               double    8  bytes
          long double   12  bytes
So ptr and base would be
  • ptr.b
    base.b
Maybe that is it?

Posted: Mon Sep 27, 2004 1:22 pm
by gkaizer
hi dare, you should be right if they were of type char, but they're pointer to type char, a pointer is 4 bytes long, always ;)

cheers

Posted: Mon Sep 27, 2004 1:30 pm
by Dare2
:oops:
Well, that was the one shot in my arsenel. Sorry about that. :)

Posted: Mon Sep 27, 2004 2:03 pm
by olejr
Don't know if this work but what if you do:

Code: Select all

*ptr.b
*base.b
This would become a pointer to .b
just like in the C example...(pointer to char)

Posted: Mon Sep 27, 2004 3:10 pm
by GedB
gkaizer,

There are 2 things wrong with this: @*deb + 2

First, *deb is a pointer. It is a variable that contains the address for deb.

Your getting a pointer to this pointer. Use *deb, not @*deb.

Second, FILE is 20 bytes long. When you use an array reference in C it calculates it based on the size of the type.

Say &_iob is at adress 0.

&_iob[0] = &iob + (0 * 20) = 0
&_iob[0] = &iob + (1 * 20) = 20
&_iob[0] = &iob + (2 * 20) = 40

The code *deb + 2 would not be pointing to 40, it would be pointing to 2. That is halfway through stdin\cnt!

However, something strange is going on. The code appears to require an extra Long at the beginning. I don't know why, you'll have to check the documentation.

Here's my code which doesn't crash. It probably doesn't work, though. I'm using a structure to declare a static array rather then using raw pointers.

Code: Select all

Structure FILE
  cnt.l
  ptr.l
  base.l
  flag.l
  fd.l
EndStructure 

Structure FILES
  dontknowwhy.l
  stdin.FILE
  stdout.FILE
  stderr.FILE
EndStructure 

Procedure main()
  memo.MEMORY_BASIC_INFORMATION
  ; *pointer = iob()
  ; Debug Hex(*pointer)
  ;fprintf(*pointer +2,"errore!")
  hInst.l = Loadlibrary_("msvcrt.dll")
  If hInst
    *pointer = GetProcAddress_(hInst,"__iob_func"); this returns a pointer To an array of type FILE
    *fpr = GetProcAddress_(hInst,"fprintf")
    If *pointer
      *deb.FILES = CallCFunctionFast(*pointer)
      If VirtualQuery_(*deb,@memo,SizeOf(memo))
        Debug memo\State ; = MEM_COMMIT, we can use this memory
      EndIf
      Debug *deb + 40
      Debug @*deb\stderr
      
      ret.l = CallCFunctionFast(*fpr,*deb\stderr,"errore!") ;
      Debug Hex(*deb)
      Debug Hex(*fpr)
    EndIf
  EndIf
  FreeLibrary_(hInst)
EndProcedure

main()

Posted: Tue Sep 28, 2004 8:19 am
by gkaizer
hi GedB, i suspected it needed a sizeof(struct.FILE)(infact i already used in my code *deb+40), but as it crashed, i posted my first code... you're are right, seems like it needs an extra long (and in the documentation i'll look for it, but it seems to me that there's nothing 'bout that)...as soon as i can i'll try your code, and let you know...thanks anyway, you've taught me sumthing :wink:

cheers

Posted: Tue Sep 28, 2004 9:20 am
by gkaizer
well my new code is

Code: Select all

Structure FILE
  cnt.l
  ptr.l
  base.l
  flag.l
  fd.l
EndStructure

Structure FILES
  stdin.FILE
  stdout.FILE
  stderr.FILE
  fileother.FILE
EndStructure

Procedure main()
  memo.MEMORY_BASIC_INFORMATION
  hInst.l = Loadlibrary_("msvcrt.dll")
  If hInst
    *pointer = GetProcAddress_(hInst,"__iob_func"); this returns a pointer to an array of type FILE
    *fpr = GetProcAddress_(hInst,"fprintf")
    If *pointer
      *deb.FILES = CallCFunctionFast(*pointer)
      If VirtualQuery_(*deb,@memo,SizeOf(memo))
        Debug memo\State ; = MEM_COMMIT, we can use this memory
      EndIf
      Debug "stderr should be " + Hex(*deb + 40)
      Debug "infact it is " + Hex(*deb\stderr)
      Debug "*deb is " + Hex(*deb)
      Debug "*fpr is " + Hex(*fpr)
      ret.l = CallCFunctionFast(*fpr,*deb+60,"errore! and %s","errore!!") ;
      ret.l = CallCFunctionFast(*fpr,*deb\fileother,"ok, it's the same")
    EndIf
  EndIf
  FreeLibrary_(hInst)
EndProcedure

main()

End

;
and as long as i use *deb+60 or *deb\fileother, no crash....i think it's like this because that is the beginning of file descriptors not reserved from the system, you can use with any file opened with fopen (i think fopen will allocate a file descriptor beginning from that area of memory).
I'll investigate more on that...

Posted: Tue Sep 28, 2004 1:37 pm
by gkaizer
ok, i changed my code like this and it doesn't crash, but no string is displayed, don't know why

Code: Select all

Structure FILE
  cnt.l
  ptr.l
  base.l
  flag.l
  fd.l
EndStructure

Structure FILES
  stdin.FILE
  stdout.FILE
  stderr.FILE
  fileother.FILE
EndStructure

Procedure main()
  memo.MEMORY_BASIC_INFORMATION
  hInst.l = Loadlibrary_("msvcrt.dll")
  If hInst
    ;*pointer = GetProcAddress_(hInst,"__iob_func"); this actually returns a pointer to a function __p__iob
    *pointer = GetProcAddress_(hInst,"_iob")
    *fpr = GetProcAddress_(hInst,"fwprintf")
    *fp = GetProcAddress_(hInst,"fputs")
    If *pointer
      *deb.FILES = *pointer
      Debug "*pointer is " +  Hex(*pointer)
      
      If VirtualQuery_(*deb,@memo,SizeOf(memo))
        Debug memo\State ; = MEM_COMMIT, we can use this memory
      EndIf
      Debug "stderr should be " + Hex(*deb + 40)
      Debug "infact it is " + Hex(*deb\stderr)
      Debug "*deb is " + Hex(*deb)
      Debug "*fpr is " + Hex(*fpr)
      ret.l = CallCFunctionFast(*fpr,*deb\stderr,"errore! and %s","errore!!") 
      ret.l = CallCFunctionFast(*fpr,*deb\fileother,"ok, it's the same")
      ret.l = CallCFunctionFast(*fp,"It is ok from puts",*deb\stderr)
    EndIf
  EndIf
  FreeLibrary_(hInst)
EndProcedure

main()

End

;
i'll see to it later..