Announcement

Collapse
No announcement yet.

Asked ; Conversion C declarations into PB declarations syntax

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Asked ; Conversion C declarations into PB declarations syntax

    Hi all,

    I have some questions about converting declaration C/C++ code into PowerBasic?. Can somebody help me if I have the right direction, if not correct me and explean with I have wrong in the declaration.

    1 ) The default for passing parameters in C/C++ is the ByVal clausule. And the default return value is int. How Is that in PowerBasic?. Can I may use the byval to in PowerBasic?

    2) What should happen if there is in C/C ++ "int *" at the back as the reference or a pointer ?
    Example : int ( __cdecl * ScopeDestroy ) ( int HandleScope) ;
    I do it like this:
    DECLARE FUNCTION ScopeDestroy cdecl LIB " Osc_DLL.dll " ALIAS " ScopeDestroy" ( ByVal HandleScope AS LONG ) AS LONG PTR

    Is that the correct manner in PowerBasic?

    3) What should happen if I get in the C / C + + declaration as an example ;
    int ( __cdecl * ShowNext) ( ScopeHandle int , double * PArrDbl ) ;
    I do this:
    DECLARE FUNCTION ShowNext cdecl LIB " Osc_DLL.dll " ALIAS " ShowNext" ( ByVal ScopeHandle AS LONG , ByRef PArrDbl AS DOUBLE PTR ) AS LONG PTR

    4 ) If there is int in C/C++ / ( __cdecl * CreateScope ) (int Prm , P_IniName char * , char * P_IniSuffix ) ;

    This are the troubles for me:
    Code:
    int (__cdecl * ScopeCreate) (int Prm, char * P_IniName,  char * P_IniSuffix);
    DECLARE FUNCTION ScopeCreate                CDECL LIB "Osc_DLL.dll" ALIAS "ScopeCreate" (BYVAL Prm AS LONG, BYREF P_IniName AS STRINGZ, BYREF P_IniSuffix AS STRINGZ) AS LONG PTR
    Code:
    int (__cdecl * ShowNext) (int ScopeHandle, double * PArrDbl);   
    DECLARE FUNCTION ShowNext                   CDECL LIB "Osc_DLL.dll" ALIAS "ShowNext" (BYVAL ScopeHandle AS LONG, BYREF PArrDbl AS DOUBLE PTR) AS LONG PTR
    I do it in PowerBASIC so :
    DECLARE FUNCTION Scope Create cdecl LIB " Osc_DLL.dll " ALIAS " Scope Create" ( ByVal Prm AS LONG , ByRef P_IniName AS Stringz , Stringz ByRef P_IniSuffix AS ) AS LONG PTR

    Can someone tell if I 'm working in the right direction because it is not very easy to C / C + + declarations to convert PowerBASIC declaration syntax.

    I would like to use in PowerBASIC library in a GUI application but first these declarations work otherwise I can not write applications. I will also convert existing VB6 applications in PowerBASIC and posts on the forum source

    Kind regards
    Stephane

  • #2
    Hi Stephane,

    it is not clear what you are trying and what is the problem. You have some stuff you are trying to do and it looks like you need help in solving the problem without giving us what the problem is...

    you have two declarations that you are converting to PowerBasic, these should be fairly straight forward.... and it looks like, the one I have actually looked at, that you are close.

    so, are you having a compiler error, is the call not working, is it crashing? is the dll name correct, is it in the right path, etc, etc, etc..

    You should probably try and be a little bit more complete in the help that you need...
    Sr. Software Development Engineer and Sr. Information Security Analyst,
    CEH, Digital Forensic Examiner

    Comment


    • #3
      Here is a summary of C pointers so you can determine how pointers are being used in your C source: http://boredzo.org/pointers/
      Erich Schulman (KT4VOL/KTN4CA)
      Go Big Orange

      Comment


      • #4
        This ...

        Code:
        int ( __cdecl * ScopeDestroy ) ( int HandleScope) ;
        is a C function pointer declaration. In other words, ScopeDestroy is a pointer to a function that returns an int and takes a Byval int as its single parameter, and uses standard C calling convention. It does not return a pointer to a long as your PowerBASIC declaration shows. The dead giveaway for function pointer declarations in C or C++ is when you have the name of the entity, i.e., ScopeDestroy, enclosed in parentheses and also containing an '*' symbol.

        It would be my guess that somewhere in the code file you are working with there is a GetProcAddress() Win Api call, as that is how the addresses of functions are oftentimes obtained in Win32. You could do the same in PowerBASIC using the Call Dword syntax. Possibly take a look at my board over in Jose Roca's Forum where I have a lot of examples of this sort of thing. Specifically, take a look at ProgExs 13 through about 17 or something like that. Here is some of ProgEx15, for example ...

        Code:
        /*
           ProgEx15
           
           In this project we'll do explicit dynamic linking with our PowerBASIC Dll -
           DllPwrBasic.dll.
           
           I consider this a very tricky, difficult subject.  Both C/C++ and PowerBASIC
           allow procedures to be called through their address.  Keep in mind that not
           only variables but procedures too have addresses.  To call a procedure 
           through its address instead of through its name one must know the full
           signature of the procedure and its return value if any.  For example, we have
           been calling Prnt in DllPwrBasic.dll, and that procedure does not return 
           anything, i.e., in 'C speak' it has a void return value; it is a standard 
           call procedure because we didn't specify otherwise and standard call is the
           PowerBASIC default; and it takes one character string pointer parameter, i.e,
           a char* in 'C speak'.  Therefore, the way a C function pointer to such a
           function would be declared in C/C++ is as follows if we name the function 
           pointer pFn...
           
           void (__stdcall* pFn)(char*); 
           
           In C/C++ C Declension is the standard function stack setup protacol, so if 
           this function was C Declension ( __cdecl ) instead of __stdcall it would look
           like this..
           
           void (*pFn)(char*);
           
           You know you are looking at a function pointer declaration when you see what
           looks like a return value (or void), followed by a set of parentheses 
           containing the '*' symbol followed by a label (*pFn), and afterwards followed 
           by what looks like a function parameter list.  Its really the middle set of
           parentheses containing the '*' symbol that's the dead givaway.  The set of
           parentheses are really important too because if they were removed the meaning
           of the entire entity would be completely changed.  If we remove the 
           parentheses we would have this...
           
           void *pFn(char*);
           
           ...which actually associates like this to the compiler...
           
           void* pFn(char*);
           
           ...and that is a function (not a function pointer) named pFn that returns a
           void*, i.e., void pointer - which can point to any quantity with an address
           and takes a char* as its single parameter.
           
           You might be wondering at this point what the utility of such a strange 
           beaste as a function pointer might be!  Believe it or not, there are some
           really cool things in advanced programming that become possible with them.
           For example, my standard setup for mapping windows messages to the message
           handling procedure that will handle a message is an array of function 
           pointers.  In my COM tutorials I used arrays of function pointers to help
           elucidate the memory structure of COM objects.  The list goes on and on.
           
           In the program below we declare the function pointer pFn.  GetProcAddress()
           returns an address, but the C or C++ compiler won't under any circumstances
           allow this address to be assigned to pFn unless we 'cast' it to a __stdcall
           function pointer that returns void, i.e., nothing, and takes a single char* 
           as a parameter.  This whole term then...
           
           void (__stdcall*)(char*) 
           
           within the containing parentheses (...) in front of GetProcAddress() 
           represents a rather complicated 'cast'.
           
           In any case, when you run the program - if DllPwrBasic is in your path, the
           Prnt Sub will be called through its address and the "Hello, World!" message
           printed.  In the next example we'll show another and more common way of doing
           this with C's typedef statement.  
        */
        #include <windows.h>
        #include <stdio.h>
        
        int main(void)
        {
         HINSTANCE hInstance;   
         void (__stdcall* pFn)(char*);             //Declaration of function pointer 
                                                   //pFn that can be used to call any 
         hInstance=LoadLibrary("DllPwrBasic.dll"); //function for which you can obtain
         if(hInstance)                             //its address if the function returns
         {                                         //void and takes a single char* as a 
            pFn=(void (__stdcall*)(char*))GetProcAddress(hInstance,"PRNT");//parameter 
            if(pFn)                          //In other words, assign to pFn the address
               pFn("Hello, World!\n");       //of "PRNT" in DllPwrBasic.dll cast to a 
            else                             //standard call function that returns void,
               puts("Couldn't Find pFn!");   //i.e., nothing, and takes a char* as its 
            FreeLibrary(hInstance);          //sole parameter.
         }
         else
            puts("Couldn't Load Library!");
         getchar();
           
         return 0;   
        }
        Last edited by Fred Harris; 6 Nov 2013, 05:29 PM.
        Fred
        "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

        Comment


        • #5
          Here's an example you can learn from and run if you care to. First a C++ dll which exports a function named DestroyScope ...

          Code:
          //Program Name = dllServer.cpp; Compiled with VC6 C++
          //cl dllServer.cpp /LD
          #include <cstdio>
          
          extern "C" __declspec(dllexport) int __cdecl DestroyScope(int iNumber)
          {
           printf("Called DestroyScope()!\n");
           return 1;
          }
          I compiled it with old VC6, but I believe it will compile into an acceptable dll with any compiler. Note I have the VC6 command line compile listed above.

          Next is a PowerBASIC Console Compiler program that explicitely loads the dll by calling LoadLibrary(), then does a GetProcAddress() on DestroyScope(). There is a 'model' Declare here which allows PowerBASIC to correctly set up a stack frame for the function pointer call using Call DWord...

          Code:
          #Compile Exe
          #Dim All
          #Include "Win32Api.inc"
          
          Declare Function pFnDestroyScope CDecl (Byval iNumber As Long) As Long
          
          Function PBMain() As Long
            Local hIns,pFn,dwReturn As Dword
          
            hIns=LoadLibrary("dllServer.dll")
            If hIns Then
               pFn=GetProcAddress(hIns,"DestroyScope")
               If pFn Then
                  Call Dword pFn Using pFnDestroyScope(12345) To dwReturn
                  Print "dwReturn = " dwReturn
               End If
            End If
            Waitkey$
          
            PBMain=0
          End Function
          Here is the console output I got ...

          Called DestroyScope()!
          dwReturn = 1

          Not sure why I took the time to do this. Stephane never says 'Thanks' and usually seems to abandon his posts. Maybe somebody else can benefit from it.
          Last edited by Fred Harris; 6 Nov 2013, 09:37 PM.
          Fred
          "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

          Comment


          • #6
            Originally posted by Fred Harris View Post
            Here's an example you can learn from and run if you care to. First a C++ dll which exports a function named DestroyScope ...

            Code:
            //Program Name = dllServer.cpp; Compiled with VC6 C++
            //cl dllServer.cpp /LD
            #include <cstdio>
            
            extern "C" __declspec(dllexport) int __cdecl DestroyScope(int iNumber)
            {
             printf("Called DestroyScope()!\n");
             return 1;
            }
            I compiled it with old VC6, but I believe it will compile into an acceptable dll with any compiler. Note I have the VC6 command line compile listed above.

            Next is a PowerBASIC Console Compiler program that explicitely loads the dll by calling LoadLibrary(), then does a GetProcAddress() on DestroyScope(). There is a 'model' Declare here which allows PowerBASIC to correctly set up a stack frame for the function pointer call using Call DWord...

            Code:
            #Compile Exe
            #Dim All
            #Include "Win32Api.inc"
            
            Declare Function pFnDestroyScope CDecl (Byval iNumber As Long) As Long
            
            Function PBMain() As Long
              Local hIns,pFn,dwReturn As Dword
            
              hIns=LoadLibrary("dllServer.dll")
              If hIns Then
                 pFn=GetProcAddress(hIns,"DestroyScope")
                 If pFn Then
                    Call Dword pFn Using pFnDestroyScope(12345) To dwReturn
                    Print "dwReturn = " dwReturn
                 End If
              End If
              Waitkey$
            
              PBMain=0
            End Function
            Here is the console output I got ...

            Called DestroyScope()!
            dwReturn = 1

            Not sure why I took the time to do this. Stephane never says 'Thanks' and usually seems to abandon his posts. Maybe somebody else can benefit from it.
            Thanks for your answer :=)

            Comment


            • #7
              Your welcome.:wave:
              Fred
              "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

              Comment


              • #8
                Originally posted by Fred Harris View Post
                Your welcome.:wave:
                Hi,

                can you answer on my questions in post 1 with an example?. I don't understand how I can this C declarations into PB declarations that's what I mean.

                Thanks
                Stephane

                Comment


                • #9
                  You're making progress, Stephane, your code is looking much better.

                  An "int" in C is probably a LONG in PowerBASIC. I think you got #1 right. I think you got #2 right.

                  On #3, you probably want more like ByRef PArrDbl AS DWORD and assign the result to a pointer? It looks, offhand, as though you've gotten a pointer to a pointer where you don't want one.

                  Mmm. The C declarations for #4 don't even look appropriate but, generally, if it says char *, you want to declare AS ASCIIZ. Possibly STRINGZ.

                  Originally posted by Stephane Fonteyne View Post
                  Hi all,

                  1 ) The default for passing parameters in C/C++ is the ByVal clausule. And the default return value is int. How Is that in PowerBasic?. Can I may use the byval to in PowerBasic?

                  2) What should happen if there is in C/C ++ "int *" at the back as the reference or a pointer ?
                  Example : int ( __cdecl * ScopeDestroy ) ( int HandleScope) ;
                  I do it like this:
                  DECLARE FUNCTION ScopeDestroy cdecl LIB " Osc_DLL.dll " ALIAS " ScopeDestroy" ( ByVal HandleScope AS LONG ) AS LONG PTR

                  Is that the correct manner in PowerBasic?

                  3) What should happen if I get in the C / C + + declaration as an example ;
                  int ( __cdecl * ShowNext) ( ScopeHandle int , double * PArrDbl ) ;
                  I do this:
                  DECLARE FUNCTION ShowNext cdecl LIB " Osc_DLL.dll " ALIAS " ShowNext" ( ByVal ScopeHandle AS LONG , ByRef PArrDbl AS DOUBLE PTR ) AS LONG PTR

                  4 ) If there is int in C/C++ / ( __cdecl * CreateScope ) (int Prm , P_IniName char * , char * P_IniSuffix ) ;

                  This are the troubles for me:
                  Code:
                  int (__cdecl * ScopeCreate) (int Prm, char * P_IniName,  char * P_IniSuffix);
                  DECLARE FUNCTION ScopeCreate                CDECL LIB "Osc_DLL.dll" ALIAS "ScopeCreate" (BYVAL Prm AS LONG, BYREF P_IniName AS STRINGZ, BYREF P_IniSuffix AS STRINGZ) AS LONG PTR
                  Code:
                  int (__cdecl * ShowNext) (int ScopeHandle, double * PArrDbl);   
                  DECLARE FUNCTION ShowNext                   CDECL LIB "Osc_DLL.dll" ALIAS "ShowNext" (BYVAL ScopeHandle AS LONG, BYREF PArrDbl AS DOUBLE PTR) AS LONG PTR
                  I do it in PowerBASIC so :
                  DECLARE FUNCTION Scope Create cdecl LIB " Osc_DLL.dll " ALIAS " Scope Create" ( ByVal Prm AS LONG , ByRef P_IniName AS Stringz , Stringz ByRef P_IniSuffix AS ) AS LONG PTR

                  Can someone tell if I 'm working in the right direction because it is not very easy to C / C + + declarations to convert PowerBASIC declaration syntax.

                  I would like to use in PowerBASIC library in a GUI application but first these declarations work otherwise I can not write applications. I will also convert existing VB6 applications in PowerBASIC and posts on the forum source

                  Kind regards
                  Stephane

                  Comment

                  Working...
                  X