How to connect a SAP ® system with PureBasic (Windows)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Stefan Schnell
User
User
Posts: 80
Joined: Wed May 07, 2003 2:53 pm
Location: Germany - Oberirsen
Contact:

How to connect a SAP ® system with PureBasic (Windows)

Post by Stefan Schnell »

SAP is the market leader in Enterprise Resoure Planing (ERP) systems. But before SAP comes into business, many systems already exist - now we call it legacy systems. It was necessary for SAP to offer a communication way between itself and the other systems. So SAP develops a lot of interfaces to do it. One of this interfaces is the Remote Function Call (RFC). With RFC it is possible to call function modules remote in SAP and vis-á-vis.
SAP offers a library, called LIBRFC32, to use RFC with external programming languages. With the next steps I will show how to use this library with PureBasic. You find a lot of stuff about LIBRFC32 in the WWW, but the most of it is not really actual. I work and test with LIBRFC version 7.10 and a non-unicode SAP Netweaver ™ system 7.01.

Bibliography
  • SAP help portal - LIBRFC32, http://help.sap.com/saphelp_nw70ehp1/he ... ameset.htm
    Help of SAP Remote Function Call API from LIBRFC32, 21.09.2009
    RFC SDK Guide, SAP Release 6.40, SAP AG, Walldorf, 2004
    SAP R/3® Kommunikation mit RFC und VB, Patrick Theobald, Vieweg Verlag, 2003 ISBN 3-528-05878-1
First contact
In the first step we will do nothing but connect and disconnect a SAP® system. At first we fill a few constants with the necessary arguments to identify the system and the user. Now look at the main procedure: we open the library LIBRFC32 and get a few informations about it. Then we connect the SAP® system with the procedure ConnectSAP. We use the constants and open the connect with RfcOpenEx. You get the handle of the RFC connection back. Check the connect with the transaction SMGW in the SAP® system. Now we disconnect the SAP® system with RfcClose, in the DisConnectSAP procedure, and close the library.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  ; Constants-----------------------------------------------------------
    Enumeration
      #RFCLib
    EndEnumeration

    #ASHost = "localhost"
    #SysNr = "00"
    #Client = "000"
    #User = "BCUSER"
    #PassWord = "minisap"
    #Language = "EN"

  ; Structures----------------------------------------------------------
    XIncludeFile "librfc32.structures.pbi"

  ; Procedure ConnectSAP------------------------------------------------
    Procedure.l ConnectSAP()

      ; Variables-------------------------------------------------------
        Protected ConString.s = #NULL$
        Protected RfcErrorInfoEx.RFC_ERROR_INFO_EX

      ConString = "ASHOST=" + #ASHost
      ConString = ConString + " SYSNR=" + #SysNr
      ConString = ConString + " CLIENT=" + #Client
      ConString = ConString + " USER=" + #User
      ConString = ConString + " PASSWD=" + #PassWord
      ConString = ConString + " LANG=" + #Language
      ;ConString = ConString + " RFC_TRACE=1"
      ;ConString = ConString + " ABAP_DEBUG=1"
      ConString = ConString + #NULL$

      ProcedureReturn CallFunction(#RFCLib, "RfcOpenEx", @ConString, _
        RfcErrorInfoEx)

    EndProcedure

  ; Procedure DisConnectSAP---------------------------------------------
    Procedure DisConnectSAP(hRFC.l)
      CallFunction(#RFCLib, "RfcClose", hRFC)
    EndProcedure

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected Release.l, Level.l, Number.l

      CallDebugger

      If OpenLibrary(#RFCLib, "librfc32.dll")
        ; Version of LibRFC---------------------------------------------
          CallFunction(#RFCLib, "RfcGetPatchLevel", @Release, @Level, _
            @Number)
          Debug "Library-Release = " + Str(Release)
          Debug "Patch-Level = " + Str(Level)
          Debug "Patch-Number = " + Str(Number)

        hRFC = ConnectSAP()

        If hRFC

          ; ------------------------------------------------------------
          ;
          ; Check connection with TAC SMGW in the SAP system
          ;
          ; ------------------------------------------------------------

          DisConnectSAP(hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

; Main------------------------------------------------------------------
  Main()

; End-------------------------------------------------------------------
End
Tell me more about you
In the one and a half step we will do a little bit more. After the connect we will get some SAP® system information with the function module RFC_SYSTEM_INFO. We define exporting, importing, changing and table parameters to transfer this information to the function module. RFC_SYSTEM_INFO only needs the importing parameter, all others are null. We call the function module with the function RfcCallReceiveEx and found a lot of system informations in the structure RFCSI. You see, how easy it is to call remote of a function module in a SAP© system. You only need the parameter and table structure to transfer data between your application and the SAP® system.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  XIncludeFile "librfc32.standard.pbi"

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected rfc_rc.l = 0
        Protected rfcsi.RFCSI
        Protected Exception.l = 0
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Changing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      CallDebugger

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = ConnectSAP()

        If hRFC

          Exporting(0)\name = #Null

          Importing(0)\name = @"RFCSI_EXPORT"
          Importing(0)\nlen = 12
          Importing(0)\addr = @rfcsi
          Importing(0)\leng = SizeOf(rfcsi)
          Importing(0)\type = #RFCTYPE_CHAR;
          Importing(1)\name = #Null

          Changing(0)\name = #Null
          Tables(0)\name = #Null

          If CallFunction(#RFCLib, "RfcCallReceiveEx", hRFC, _
            @"RFC_SYSTEM_INFO", @Exporting(), @Importing(), _
            @Changing(), @Tables(), @Exception) = #RFC_OK

            Debug "Host: " + rfcsi\rfchost
            Debug "SID: " + rfcsi\rfcsysid
            Debug "DBHost: " +rfcsi\rfcdbhost

          EndIf

          DisConnectSAP(hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

; Main------------------------------------------------------------------
  Main()

; End-------------------------------------------------------------------
End
librfc32.standard.pbi

Code: Select all

; Begin-----------------------------------------------------------------

  ; Constants-----------------------------------------------------------
    XIncludeFile "librfc32.constants.pbi"

    Enumeration
      #RFCLib
    EndEnumeration

    #ASHost = "localhost"
    #SysNr = "00"
    #Client = "000"
    #User = "BCUSER"
    #PassWord = "minisap"
    #Language = "EN"

  ; Structures----------------------------------------------------------
    XIncludeFile "librfc32.structures.pbi"

  ; Procedure ConnectSAP------------------------------------------------
    Procedure.l ConnectSAP()

      ; Variables-------------------------------------------------------
        Protected ConString.s = #NULL$
        Protected RfcErrorInfoEx.RFC_ERROR_INFO_EX

      ConString = "ASHOST=" + #ASHost
      ConString = ConString + " SYSNR=" + #SysNr
      ConString = ConString + " CLIENT=" + #Client
      ConString = ConString + " USER=" + #User
      ConString = ConString + " PASSWD=" + #PassWord
      ConString = ConString + " LANG=" + #Language
      ;ConString = ConString + " RFC_TRACE=1"
      ;ConString = ConString + " ABAP_DEBUG=1"
      ConString = ConString + #NULL$

      ProcedureReturn CallFunction(#RFCLib, "RfcOpenEx", @ConString, RfcErrorInfoEx)

    EndProcedure

  ; Procedure DisConnectSAP---------------------------------------------
    Procedure DisConnectSAP(hRFC.l)
      CallFunction(#RFCLib, "RfcClose", hRFC)
    EndProcedure

; End-------------------------------------------------------------------
librfc32.structures.pbi

Code: Select all

; Begin-----------------------------------------------------------------

  Structure RFC_ERROR_INFO_EX
    group.l
    key.s{33}
    message.s{513}
  EndStructure

  Structure RFC_PARAMETER
    *name
    nlen.l
    type.l
    leng.l
    *addr
  EndStructure

  Structure RFC_TABLE
    *name
    nlen.l
    type.l
    leng.l
    ithandle.l
    itmode.l
    newitab.l
  EndStructure

  Structure RFCSI
    rfcproto.s{3}
    rfcchartyp.s{4}
    rfcinttyp.s{3}
    rfcflotyp.s{3}
    rfcdest.s{32}
    rfchost.s{8}
    rfcsysid.s{8}
    rfcdatabs.s{8}
    rfcdbhost.s{32}
    rfcdbsys.s{10}
    rfcsaprl.s{4}
    rfcmach.s{5}
    rfcopsys.s{10}
    rfctzone.s{6}
    rfcdayst.s{1}
    rfcipaddr.s{15}
    rfckernrl.s{4}
    rfchost2.s{32}
    rfcsi_resv.s{12}
    rfcipv6addr.s{45}
  EndStructure

; End-------------------------------------------------------------------
librfc32.constants.pbi

Code: Select all

; Begin-----------------------------------------------------------------

  ; ABAP/4 data types---------------------------------------------------
    Enumeration
      #TYPC
      #TYPDATE
      #TYPP
      #TYPTIME
      #TYPX
      #TYPTABH
      #TYPNUM
      #TYPFLOAT
      #TYPINT
      #TYPINT2
      #TYPINT1
      ;#TYPW
      #TYP1 = 12
      #TYP2
      #TYPDECF16 = 23
      #TYPDECF34
    EndEnumeration

  ; RFC data types------------------------------------------------------
    Enumeration
      #RFCTYPE_CHAR = #TYPC
      #RFCTYPE_DATE = #TYPDATE
      #RFCTYPE_BCD = #TYPP
      #RFCTYPE_TIME = #TYPTIME
      #RFCTYPE_BYTE = #TYPX
      #RFCTYPE_ITAB = #TYPTABH
      #RFCTYPE_NUM = #TYPNUM
      #RFCTYPE_FLOAT= #TYPFLOAT
      #RFCTYPE_INT = #TYPINT
      #RFCTYPE_INT2 = #TYPINT2
      #RFCTYPE_INT1 = #TYPINT1
      #RFCTYPE_DATE_1 = #TYP1
      #RFCTYPE_DATE_2 = #TYP2
      #RFCTYPE_NULL
      #RFCTYPE_WIDE_2
      #RFCTYPE_WIDE_4
      #RFCTYPE_STRUCTURE
      #RFCTYPE_ABAP4OBJECT
      #RFCTYPE_IUNKNOWN
      #RFCTYPE_WSTRING
      #RFCTYPE_SAPAUTOMATION
      #RFCTYPE_STUB
      #RFCTYPE_WIRE_OBJECT
      #RFCTYPE_BLOB
      #RFCTYPE_CORBA_OBJECT
      #RFCTYPE_PADDING
      #RFCTYPE_UNICODE
      #RFCTYPE_XMLDATA
      #RFCTYPE_STRING
      #RFCTYPE_XSTRING
      #RFCTYPE_DECF16
      #RFCTYPE_DECF34
    EndEnumeration

  ; RFC return codes---------------------------------------------------
    Enumeration
      #RFC_OK                          ;O.K.
      #RFC_FAILURE                     ;Error occurred
      #RFC_EXCEPTION                   ;Exception raised
      #RFC_SYS_EXCEPTION               ;System exception raised
      #RFC_CALL                        ;Call received
      #RFC_INTERNAL_COM                ;Internal communication
      #RFC_CLOSED                      ;Connection closed
      #RFC_RETRY                       ;No Data yet
      #RFC_NO_TID                      ;No Transaction ID available
      #RFC_EXECUTED                    ;Function already executed
      #RFC_SYNCHRONIZE                 ;Synchronous Call in Progress
      #RFC_MEMORY_INSUFFICIENT         ;Memory insufficient
      #RFC_VERSION_MISMATCH            ;Version mismatch
      #RFC_NOT_FOUND                   ;Function Not found
      #RFC_CALL_NOT_SUPPORTED          ;This call is Not supported
      #RFC_NOT_OWNER                   ;Caller does Not own the handle
      #RFC_NOT_INITIALIZED             ;RFC Not yet initialized
      #RFC_SYSTEM_CALLED               ;A system call is executed
      #RFC_INVALID_HANDLE              ;Invalid handle passed to API
      #RFC_INVALID_PARAMETER           ;Invalid parameter passed to API
      #RFC_CANCELED                    ;RFC call canceled by user
      #RFC_CONVERSION                  ;Conversation error detected
      #RFC_INVALID_PROTOCOL            ;Received data has bad format
      #RFC_TIMEOUT
    EndEnumeration

  ; RFC error group-----------------------------------------------------
    Enumeration
      #RFC_ERROR_PROGRAM = 101         ;Error in RFC program
      #RFC_ERROR_COMMUNICATION         ;Error in network/communications
      #RFC_ERROR_LOGON_FAILURE         ;SAP logon error
      #RFC_ERROR_SYSTEM_FAILURE        ;SAP system exception raised
      #RFC_ERROR_APPLICATION_EXCEPTION ;Function module raised exception
      #RFC_ERROR_RESOURCE              ;Resource not available
      #RFC_ERROR_PROTOCOL              ;RFC protocol error
      #RFC_ERROR_INTERNAL              ;RFC internal error
      #RFC_ERROR_CANCELLED             ;RFC server was cancelled
      #RFC_ERROR_BUSY                  ;System is busy
    EndEnumeration

  ; RFC_ITMODE - mode how to pass internal table------------------------
    Enumeration
      #RFC_ITMODE_BYREFERENCE          ;Table is passed by reference
      #RFC_ITMODE_BYVALUE              ;Table is passed by value
      #RFC_ITMODE_KEEPALIVE            ;Table is passed by reference,
                                       ;but is kept alive after return
    EndEnumeration

; End-------------------------------------------------------------------
Last edited by Stefan Schnell on Tue Jun 15, 2010 3:09 pm, edited 1 time in total.
User avatar
Stefan Schnell
User
User
Posts: 80
Joined: Wed May 07, 2003 2:53 pm
Location: Germany - Oberirsen
Contact:

How to connect a SAP® system with PureBasic - Step 2

Post by Stefan Schnell »

Show me the things from inside
Now we use the function module RFC_READ_TABLE to get the content of a table from a SAP® sytem. We fill the exporting and table parameters and here we stop. It is necessary to create an internal table. We do that with the ItCreate function for fields and data. Then we call the RFC_READ_TABLE function module and get the result in fields and data tables. Do not forget to free the internal tables with ItFree function.

Intermission
If you want a lot of more detailed informations activate the SQL and RFC trace from the performance analysis with the transaction code ST05. After you have done your work, deactivate the trace and display it. You can see exactly what the SAP® system has done.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  XIncludeFile "librfc32.standard.pbi"

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected hItData.l = 0
        Protected hItFields.l = 0
        Protected Release.l, Level.l, Number.l
        Protected rfc_rc.l = 0
        Protected Exception.l = 0
        Protected i.l = 0
        Protected LineAddr.l = 0
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Changing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      CallDebugger

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = ConnectSAP()

        If hRFC

          Exporting(0)\name = @"QUERY_TABLE"
          Exporting(0)\nlen = 11
          Exporting(0)\type = #RFCTYPE_CHAR
          Exporting(0)\leng = 5
          Exporting(0)\addr = @"USR02"

          Exporting(1)\name = @"DELIMITER"
          Exporting(1)\nlen = 9
          Exporting(1)\type = #RFCTYPE_CHAR
          Exporting(1)\leng = 1
          Exporting(1)\addr = @"~"

          Exporting(2)\name = #Null

          Importing(0)\name = #Null

          Changing(0)\name = #Null

          Tables(0)\name = @"FIELDS"
          Tables(0)\nlen = 6
          Tables(0)\type = #RFCTYPE_CHAR
          Tables(0)\leng = 103
          Tables(0)\itmode = #RFC_ITMODE_BYREFERENCE
          hItFields = CallFunction(#RFCLib, "ItCreate", @"FIELDS", _
            103, 0, 0)
          Tables(0)\ithandle = hItFields
          Tables(0)\newitab  = 0

          Tables(1)\name = @"DATA"
          Tables(1)\nlen = 4
          Tables(1)\type = #RFCTYPE_CHAR
          Tables(1)\leng = 512
          Tables(1)\itmode = #RFC_ITMODE_BYREFERENCE
          hItData = CallFunction(#RFCLib, "ItCreate", @"DATA", _
            512, 0, 0)
          Tables(1)\ithandle = hItData
          Tables(1)\newitab  = 0

          Tables(2)\name = #Null

          If CallFunction(#RFCLib, "RfcCallReceiveEx", hRFC, _
            @"RFC_READ_TABLE", @Exporting(), @Importing(), _
            @Changing(), @Tables(), @Exception) = #RFC_OK

            ; Show the field names--------------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItFields)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItFields, i)
                Debug "Fieldname: " + PeekS(LineAddr, 30) + _
                  " / Fieldtext: " + PeekS(LineAddr + 43, 60)
              Next i

            ; Show the data---------------------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItData)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItData, i)
                Debug PeekS(LineAddr)
              Next i

          EndIf

          CallFunction(#RFCLib, "ItFree", hItData)
          CallFunction(#RFCLib, "ItFree", hItFields)

          DisConnectSAP(hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

; Main------------------------------------------------------------------
  Main()

; End-------------------------------------------------------------------
End
Now I will show you how to fill the internal tables with data to select special fields from a table. All you must do is to use the ItAppendRow function and add content to the intenal table - that is all.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  XIncludeFile "librfc32.standard.pbi"

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected hItData.l = 0
        Protected hItFields.l = 0
        Protected Release.l, Level.l, Number.l
        Protected rfc_rc.l = 0
        Protected Exception.l = 0
        Protected i.l = 0
        Protected LineAddr.l = 0
        Protected Row.s = #NULL$
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Changing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      CallDebugger

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = ConnectSAP()

        If hRFC

          Exporting(0)\name = @"QUERY_TABLE"
          Exporting(0)\nlen = 11
          Exporting(0)\type = #RFCTYPE_CHAR
          Exporting(0)\leng = 5
          Exporting(0)\addr = @"USR02"

          Exporting(1)\name = @"DELIMITER"
          Exporting(1)\nlen = 9
          Exporting(1)\type = #RFCTYPE_CHAR
          Exporting(1)\leng = 1
          Exporting(1)\addr = @"~"

          Exporting(2)\name = #Null

          Importing(0)\name = #Null

          Changing(0)\name = #Null

          Tables(0)\name = @"FIELDS"
          Tables(0)\nlen = 6
          Tables(0)\type = #RFCTYPE_CHAR
          Tables(0)\leng = 103
          Tables(0)\itmode = #RFC_ITMODE_BYREFERENCE
          hItFields = CallFunction(#RFCLib, "ItCreate", @"FIELDS", _
            103, 0, 0)
          Tables(0)\ithandle = hItFields
          Tables(0)\newitab  = 0

          Tables(1)\name = @"DATA"
          Tables(1)\nlen = 4
          Tables(1)\type = #RFCTYPE_CHAR
          Tables(1)\leng = 512
          Tables(1)\itmode = #RFC_ITMODE_BYREFERENCE
          hItData = CallFunction(#RFCLib, "ItCreate", @"DATA", _
            512, 0, 0)
          Tables(1)\ithandle = hItData
          Tables(1)\newitab  = 0

          Tables(2)\name = #Null

          ; Select the fields you want----------------------------------
            ; Username--------------------------------------------------
              Row = "BNAME"
              Row = Row + Space(103 - Len(Row))
              CallFunction(#RFCLib, "ItAppendRow", hItFields, @Row, 103)
            ; Valid from------------------------------------------------
              Row = "GLTGV"
              Row = Row + Space(103 - Len(Row))
              CallFunction(#RFCLib, "ItAppendRow", hItFields, @Row, 103)
            ; Valid to--------------------------------------------------
              Row = "GLTGB"
              Row = Row + Space(103 - Len(Row))
              CallFunction(#RFCLib, "ItAppendRow", hItFields, @Row, 103)

          If CallFunction(#RFCLib, "RfcCallReceiveEx", hRFC, _
            @"RFC_READ_TABLE", @Exporting(), @Importing(), _
            @Changing(), @Tables(), @Exception) = #RFC_OK

            ; Show the selected field names-----------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItFields)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItFields, i)
                Debug PeekS(LineAddr, 30)
              Next i

            ; Show the data---------------------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItData)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItData, i)
                Debug PeekS(LineAddr)
              Next i

          EndIf

          If Exception
            Debug "Exception " + Str(Exception) + " occured!"
          EndIf

          CallFunction(#RFCLib, "ItFree", hItData)
          CallFunction(#RFCLib, "ItFree", hItFields)

          DisConnectSAP(hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

; Main------------------------------------------------------------------
  Main()

; End-------------------------------------------------------------------
End
User avatar
Stefan Schnell
User
User
Posts: 80
Joined: Wed May 07, 2003 2:53 pm
Location: Germany - Oberirsen
Contact:

How to connect a SAP® system with PureBasic - Step 3

Post by Stefan Schnell »

I want all and I want it now
The standard RFC_READ_TABLE function module has frontiers: A major frontier is, that is not possible to get data with a size bigger than 512 bytes. A minor frontier is, that it is not possible to sort the data before it returns. I take this two changes and save the new function module with the name Z_RFC_READ_TABLE in my namespace. You will find it below. I also changed the function module to use it with the Java™ connector, it is a solution from the SAP® Developer Network (SDN). In this step we will use the additional sort function. And, if you look to the detail, you see, the size of data has changed from 512 to 8192 bytes.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  XIncludeFile "librfc32.standard.pbi"

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected hItData.l = 0
        Protected hItFields.l = 0
        Protected Release.l, Level.l, Number.l
        Protected rfc_rc.l = 0
        Protected Exception.l
        Protected i.l
        Protected LineAddr.l
        Protected Row.s = #NULL$
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Changing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = ConnectSAP()

        If hRFC

          Exporting(0)\name = @"QUERY_TABLE"
          Exporting(0)\nlen = 11
          Exporting(0)\type = #RFCTYPE_CHAR
          Exporting(0)\leng = 5
          Exporting(0)\addr = @"USR02"

          Exporting(1)\name = @"DELIMITER"
          Exporting(1)\nlen = 9
          Exporting(1)\type = #RFCTYPE_CHAR
          Exporting(1)\leng = 1
          Exporting(1)\addr = @"~"

          ; Sorting example---------------------------------------------
            Exporting(2)\name = @"SORT"
            Exporting(2)\nlen = 4
            Exporting(2)\type = #RFCTYPE_CHAR
            Exporting(2)\leng = 8
            Exporting(2)\addr = @"PASSCODE"

          Exporting(3)\name = #Null

          Importing(0)\name = #Null

          Changing(0)\name = #Null

          Tables(0)\name = @"FIELDS"
          Tables(0)\nlen = 6
          Tables(0)\type = #RFCTYPE_CHAR
          Tables(0)\leng = 103
          Tables(0)\itmode = #RFC_ITMODE_BYREFERENCE
          hItFields = CallFunction(#RFCLib, "ItCreate", @"FIELDS", _
            103, 0, 0)
          Tables(0)\ithandle = hItFields
          Tables(0)\newitab  = 0

          Tables(1)\name = @"DATA"
          Tables(1)\nlen = 4
          Tables(1)\type = #RFCTYPE_CHAR
          Tables(1)\leng = 8192
          Tables(1)\itmode = #RFC_ITMODE_BYREFERENCE
          hItData = CallFunction(#RFCLib, "ItCreate", @"DATA", _
            8192, 0, 0)
          Tables(1)\ithandle = hItData
          Tables(1)\newitab  = 0

          Tables(2)\name = #Null

          ; Select the fields you want----------------------------------
            ; Username--------------------------------------------------
              Row = "BNAME"
              Row = Row + Space(103 - Len(Row))
              CallFunction(#RFCLib, "ItAppendRow", hItFields, @Row, 103)
            ; Passcode--------------------------------------------------
              Row = "PASSCODE"
              Row = Row + Space(103 - Len(Row))
              CallFunction(#RFCLib, "ItAppendRow", hItFields, @Row, 103)

          If CallFunction(#RFCLib, "RfcCallReceiveEx", hRFC, _
            @"Z_RFC_READ_TABLE", @Exporting(), @Importing(), _
            @Changing(), @Tables(), @Exception) = #RFC_OK

            ; Show the selected fields----------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItFields)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItFields, i)
                Debug PeekS(LineAddr, 30)
              Next i

            ; Show the data---------------------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItData)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItData, i)
                Debug PeekS(LineAddr)
              Next i

          EndIf

          If Exception
            Debug "Exception " + Str(Exception) + " occured!"
          EndIf

          CallFunction(#RFCLib, "ItFree", hItData)
          CallFunction(#RFCLib, "ItFree", hItFields)

          DisConnectSAP(hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

; Main------------------------------------------------------------------
  Main()

; End-------------------------------------------------------------------
End
In the next listing we use a table with a line size bigger than 512 bytes.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  XIncludeFile "librfc32.standard.pbi"

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected hItData.l = 0
        Protected hItFields.l = 0
        Protected Release.l, Level.l, Number.l
        Protected rfc_rc.l = 0
        Protected Exception.l
        Protected i.l
        Protected LineAddr.l
        Protected Row.s = #NULL$
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Changing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = ConnectSAP()

        If hRFC

          ; Example for line length bigger then 512 bytes---------------
            Exporting(0)\name = @"QUERY_TABLE"
            Exporting(0)\nlen = 11
            Exporting(0)\type = #RFCTYPE_CHAR
            Exporting(0)\leng = 5
            Exporting(0)\addr = @"USR04"

          Exporting(1)\name = @"DELIMITER"
          Exporting(1)\nlen = 9
          Exporting(1)\type = #RFCTYPE_CHAR
          Exporting(1)\leng = 1
          Exporting(1)\addr = @"~"

          Exporting(2)\name = #Null

          Importing(0)\name = #Null

          Changing(0)\name = #Null

          Tables(0)\name = @"FIELDS"
          Tables(0)\nlen = 6
          Tables(0)\type = #RFCTYPE_CHAR
          Tables(0)\leng = 103
          Tables(0)\itmode = #RFC_ITMODE_BYREFERENCE
          hItFields = CallFunction(#RFCLib, "ItCreate", @"FIELDS", _
            103, 0, 0)
          Tables(0)\ithandle = hItFields
          Tables(0)\newitab  = 0

          Tables(1)\name = @"DATA"
          Tables(1)\nlen = 4
          Tables(1)\type = #RFCTYPE_CHAR
          Tables(1)\leng = 8192
          Tables(1)\itmode = #RFC_ITMODE_BYREFERENCE
          hItData = CallFunction(#RFCLib, "ItCreate", @"DATA", _
            8192, 0, 0)
          Tables(1)\ithandle = hItData
          Tables(1)\newitab  = 0

          Tables(2)\name = #Null

          If CallFunction(#RFCLib, "RfcCallReceiveEx", hRFC, _
            @"Z_RFC_READ_TABLE", @Exporting(), @Importing(), _
            @Changing(), @Tables(), @Exception) = #RFC_OK

            ; Show the selected fields----------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItFields)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItFields, i)
                Debug PeekS(LineAddr, 30)
              Next i

            ; Show the data---------------------------------------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItData)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", hItData, i)
                Debug PeekS(LineAddr)
              Next i

          EndIf

          If Exception
            Debug "Exception " + Str(Exception) + " occured!"
          EndIf

          CallFunction(#RFCLib, "ItFree", hItData)
          CallFunction(#RFCLib, "ItFree", hItFields)

          DisConnectSAP(hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

; Main------------------------------------------------------------------
  Main()

; End-------------------------------------------------------------------
End

Code: Select all

FUNCTION Z_RFC_READ_TABLE2.

*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     VALUE(QUERY_TABLE) TYPE  DD02L-TABNAME
*"     VALUE(DELIMITER) TYPE  SONV-FLAG DEFAULT SPACE
*"     VALUE(NO_DATA) TYPE  SONV-FLAG DEFAULT SPACE
*"     VALUE(ROWSKIPS) TYPE  SOID-ACCNT DEFAULT 0
*"     VALUE(ROWCOUNT) TYPE  SOID-ACCNT DEFAULT 0
*"     VALUE(SORT) TYPE  CHAR1024 DEFAULT SPACE
*"  TABLES
*"      OPTIONS STRUCTURE  RFC_DB_OPT
*"      FIELDS STRUCTURE  RFC_DB_FLD
*"      DATA STRUCTURE  ZTAB8192
*"  EXCEPTIONS
*"      TABLE_NOT_AVAILABLE
*"      TABLE_WITHOUT_DATA
*"      OPTION_NOT_VALID
*"      FIELD_NOT_VALID
*"      NOT_AUTHORIZED
*"      DATA_BUFFER_EXCEEDED
*"----------------------------------------------------------------------

"-->Changed Begin<------------------------------------------------------
"
"  Add in import the parameter SORT with the type CHAR1024 and the
"  default value space, activate optional and pass value. This gives
"  you the possibility to create sorted output in DATA.
"
"  Create a domain called ZSYSCHAR8192 with the data type CHAR and the
"  length 8192. Create a structure called ZTAB8192 with the component
"  WA and the new component type ZSYSCHAR8192. In this data type add
"  the domain ZSYSCHAR8192. This gives you the possibility to transfer
"  line length bigger than 512 bytes.
"
"-->Changed End<--------------------------------------------------------

CALL FUNCTION 'VIEW_AUTHORITY_CHECK'
     EXPORTING
          VIEW_ACTION                    = 'S'
          VIEW_NAME                      = QUERY_TABLE
     EXCEPTIONS
          NO_AUTHORITY                   = 2
          NO_CLIENTINDEPENDENT_AUTHORITY = 2
          NO_LINEDEPENDENT_AUTHORITY     = 2
          OTHERS                         = 1.

IF SY-SUBRC = 2.
  RAISE NOT_AUTHORIZED.
ELSEIF SY-SUBRC = 1.
  RAISE TABLE_NOT_AVAILABLE.
ENDIF.

* ----------------------------------------------------------------------
*  find out about the structure of QUERY_TABLE
* ----------------------------------------------------------------------
DATA BEGIN OF TABLE_STRUCTURE OCCURS 10.
        INCLUDE STRUCTURE DFIES.
DATA END OF TABLE_STRUCTURE.
"DATA TABLE_HEADER LIKE X030L.
DATA TABLE_TYPE TYPE DD02V-TABCLASS.

CALL FUNCTION 'DDIF_FIELDINFO_GET'
  EXPORTING
    TABNAME              = QUERY_TABLE
*   FIELDNAME            = ' '
*   LANGU                = SY-LANGU
*   LFIELDNAME           = ' '
*   ALL_TYPES            = ' '
*   GROUP_NAMES          = ' '
  IMPORTING
*   X030L_WA             =
    DDOBJTYPE            = TABLE_TYPE
*   DFIES_WA             =
*   LINES_DESCR          =
  TABLES
    DFIES_TAB            = TABLE_STRUCTURE
*   FIXED_VALUES         =
  EXCEPTIONS
    NOT_FOUND            = 1
    INTERNAL_ERROR       = 2
    OTHERS               = 3
          .
IF SY-SUBRC <> 0.
  RAISE TABLE_NOT_AVAILABLE.
ENDIF.
IF TABLE_TYPE = 'INTTAB'.
  RAISE TABLE_WITHOUT_DATA.
ENDIF.

* ----------------------------------------------------------------------
*  isolate first field of DATA as output field
*  (i.e. allow for changes to structure DATA!)
* ----------------------------------------------------------------------
DATA LINE_LENGTH TYPE I.
FIELD-SYMBOLS <D>.
ASSIGN COMPONENT 0 OF STRUCTURE DATA TO <D>.
DESCRIBE FIELD <D> LENGTH LINE_LENGTH in character mode.

* ----------------------------------------------------------------------
*  if FIELDS are not specified, read all available fields
* ----------------------------------------------------------------------
DATA NUMBER_OF_FIELDS TYPE I.
DESCRIBE TABLE FIELDS LINES NUMBER_OF_FIELDS.
IF NUMBER_OF_FIELDS = 0.
  LOOP AT TABLE_STRUCTURE.
    MOVE TABLE_STRUCTURE-FIELDNAME TO FIELDS-FIELDNAME.
    APPEND FIELDS.
  ENDLOOP.
ENDIF.

* ----------------------------------------------------------------------
*  for each field which has to be read, copy structure information
*  into tables FIELDS_INT (internal use) and FIELDS (output)
* ----------------------------------------------------------------------
DATA: BEGIN OF FIELDS_INT OCCURS 10,
        FIELDNAME  LIKE TABLE_STRUCTURE-FIELDNAME,
        TYPE       LIKE TABLE_STRUCTURE-INTTYPE,
        DECIMALS   LIKE TABLE_STRUCTURE-DECIMALS,
        LENGTH_SRC LIKE TABLE_STRUCTURE-INTLEN,
        LENGTH_DST LIKE TABLE_STRUCTURE-LENG,
        OFFSET_SRC LIKE TABLE_STRUCTURE-OFFSET,
        OFFSET_DST LIKE TABLE_STRUCTURE-OFFSET,
      END OF FIELDS_INT,
      LINE_CURSOR TYPE I.

LINE_CURSOR = 0.
*  for each field which has to be read ...
LOOP AT FIELDS.

  READ TABLE TABLE_STRUCTURE WITH KEY FIELDNAME = FIELDS-FIELDNAME.
  IF SY-SUBRC NE 0.
    RAISE FIELD_NOT_VALID.
  ENDIF.

* compute the place for field contents in DATA rows:
* if not first field in row, allow space for delimiter
  IF LINE_CURSOR <> 0.
    IF NO_DATA EQ SPACE AND DELIMITER NE SPACE.
      MOVE DELIMITER TO DATA+LINE_CURSOR.
    ENDIF.
    LINE_CURSOR = LINE_CURSOR + STRLEN( DELIMITER ).
  ENDIF.

* ... copy structure information into tables FIELDS_INT
* (which is used internally during SELECT) ...
  FIELDS_INT-FIELDNAME  = TABLE_STRUCTURE-FIELDNAME.
  FIELDS_INT-LENGTH_SRC = TABLE_STRUCTURE-INTLEN.
  FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-LENG.
  FIELDS_INT-OFFSET_SRC = TABLE_STRUCTURE-OFFSET.
  FIELDS_INT-OFFSET_DST = LINE_CURSOR.
  FIELDS_INT-TYPE       = TABLE_STRUCTURE-INTTYPE.
  FIELDS_INT-DECIMALS   = TABLE_STRUCTURE-DECIMALS.
* compute the place for contents of next field in DATA rows
  LINE_CURSOR = LINE_CURSOR + TABLE_STRUCTURE-LENG.
  IF LINE_CURSOR > LINE_LENGTH AND NO_DATA EQ SPACE.
    RAISE DATA_BUFFER_EXCEEDED.
  ENDIF.
  APPEND FIELDS_INT.

* ... and into table FIELDS (which is output to the caller)
  FIELDS-FIELDTEXT = TABLE_STRUCTURE-FIELDTEXT.
  FIELDS-TYPE      = TABLE_STRUCTURE-INTTYPE.
  FIELDS-LENGTH    = FIELDS_INT-LENGTH_DST.
  FIELDS-OFFSET    = FIELDS_INT-OFFSET_DST.
  MODIFY FIELDS.

ENDLOOP.
* end of loop at FIELDS

* ----------------------------------------------------------------------
*  read data from the database and copy relevant portions into DATA
* ----------------------------------------------------------------------
* output data only if NO_DATA equals space (otherwise the structure
* information in FIELDS is the only result of the module)
IF NO_DATA EQ SPACE.

"-->Changed Begin<------------------------------------------------------

" DATA: BEGIN OF WORK, BUFFER(30000), END OF WORK.
  DATA: DREF TYPE REF TO DATA.

  FIELD-SYMBOLS: <WA> TYPE ANY, <COMP> TYPE ANY.

" ASSIGN WORK TO <WA> CASTING TYPE (QUERY_TABLE).
" IF ROWCOUNT > 0.
"   ROWCOUNT = ROWCOUNT + ROWSKIPS.
" ENDIF.
  CREATE DATA DREF TYPE (QUERY_TABLE).
  ASSIGN DREF->* TO <WA>.

"  SELECT * FROM (QUERY_TABLE) INTO <WA> WHERE (OPTIONS).
  SELECT * FROM (QUERY_TABLE) INTO <WA> WHERE (OPTIONS) ORDER BY (SORT).

"-->Changed End<--------------------------------------------------------

    IF SY-DBCNT GT ROWSKIPS.

*   copy all relevant fields into DATA (output) table
      LOOP AT FIELDS_INT.
        IF FIELDS_INT-TYPE = 'P'.
        ASSIGN COMPONENT FIELDS_INT-FIELDNAME
            OF STRUCTURE <WA> TO <COMP>
            TYPE     FIELDS_INT-TYPE
            DECIMALS FIELDS_INT-DECIMALS.
        ELSE.
        ASSIGN COMPONENT FIELDS_INT-FIELDNAME
            OF STRUCTURE <WA> TO <COMP>
            TYPE     FIELDS_INT-TYPE.
        ENDIF.
        MOVE <COMP> TO
            <D>+FIELDS_INT-OFFSET_DST(FIELDS_INT-LENGTH_DST).
      ENDLOOP.
*   end of loop at FIELDS_INT
      APPEND DATA.

      IF ROWCOUNT > 0 AND SY-DBCNT GE ROWCOUNT. EXIT. ENDIF.

    ENDIF.

  ENDSELECT.

ENDIF.

ENDFUNCTION.
User avatar
Stefan Schnell
User
User
Posts: 80
Joined: Wed May 07, 2003 2:53 pm
Location: Germany - Oberirsen
Contact:

How to connect a SAP® system with PureBasic - Step 4

Post by Stefan Schnell »

Writing love letters to ABAP®

Patrick Theobald presents in his book in chapter 6.1 an example for the .NET-Connector, called ABAP interpreter as client proxy (from side 164 to 171). I translate this example to PureBasic. In the following step you will find a small application with a smart GUI. In the top editor gadget you can code an ABAP program. With the go button you transfer it to the SAP® system and excute it with the function RFC_ABAP_INSTALL_AND_RUN. In the down editor gadget you see the results.

Intermission
If you want to list all function modules with short text use tables TFDIR and TFTIT. Alternatively you can use the function module RFC_FUNCTION_DOCU_GET.

Important hint
If you want to use the function module RFC_ABAP_INSTALL_AND_RUN, it is necessary to have development rights on the connected system.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  XIncludeFile "librfc32.standard.pbi"

  ; Procedure RunABAP---------------------------------------------------
    Procedure RunABAP()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected hItProgram.l = 0
        Protected hItWrites.l = 0
        Protected i.l = 0
        Protected LineAddr.l = 0
        Protected Exception.l = 0
        Protected Row.s = #NULL$
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Changing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = ConnectSAP()

        If hRFC

          Exporting(0)\name = #Null
          Importing(0)\name = #Null
          Changing(0)\name = #Null

          Tables(0)\name = @"PROGRAM"
          Tables(0)\nlen = 7
          Tables(0)\type = #RFCTYPE_CHAR
          Tables(0)\leng = 72
          Tables(0)\itmode = #RFC_ITMODE_BYREFERENCE
          hItProgram = CallFunction(#RFCLib, "ItCreate", @"PROGRAM", _
            72, 0, 0)
          Tables(0)\ithandle = hItProgram
          Tables(0)\newitab  = 0

          Tables(1)\name = @"WRITES"
          Tables(1)\nlen = 6
          Tables(1)\type = #RFCTYPE_CHAR
          Tables(1)\leng = 256
          Tables(1)\itmode = #RFC_ITMODE_BYREFERENCE
          hItWrites = CallFunction(#RFCLib, "ItCreate", @"WRITES", _
            256, 0, 0)
          Tables(1)\ithandle = hItWrites
          Tables(1)\newitab  = 0

          Tables(2)\name = #Null

          ; Read source from editor and transfer to program table-------
            For i = 0 To CountGadgetItems(#Editor) - 1
              Row = GetGadgetItemText(#Editor, i)
              Row = Row + Space(72 - Len(Row))
              CallFunction(#RFCLib, "ItAppendRow", hItProgram, _
                @Row, Len(Row))
            Next i

          If CallFunction(#RFCLib, "RfcCallReceiveEx", hRFC, _
            @"RFC_ABAP_INSTALL_AND_RUN", @Exporting(), @Importing(), _
            @Changing(), @Tables(), @Exception) = #RFC_OK
            ClearGadgetItems(#Output)
            ; Read write table and transfer result to output------------
              For i = 1 To CallFunction(#RFCLib, "ItFill", hItWrites)
                LineAddr = CallFunction(#RFCLib, "ItGetLine", _
                  hItWrites, i)
                AddGadgetItem(#Output, -1, PeekS(LineAddr, 256))
              Next i
          EndIf

          DisConnectSAP(hRFC)

        EndIf

        CallFunction(#RFCLib, "ItFree", hItProgram)
        CallFunction(#RFCLib, "ItFree", hItWrites)
        CloseLibrary(#RFCLib)

      EndIf
    EndProcedure

  ; Procedure Init------------------------------------------------------
    Procedure Init()
      If OpenWindow(#MainWin, 10, 10, 640, 640, "From PureBasic to ABAP", _
        #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
        EditorGadget(#Editor, 10, 10, 620, 290)
        EditorGadget(#Output, 10, 340, 620, 290, #PB_Editor_ReadOnly)
        ButtonGadget(#Go, 10, 310, 120, 20, "Go")
      EndIf
    EndProcedure

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected Event.l = 0
        Protected Quit.b = 0

      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_Gadget
            Select EventGadget()
              Case #Go
                RunABAP()
            EndSelect
          Case #PB_Event_CloseWindow
            Quit = 1
        EndSelect
      Until Quit = 1

    EndProcedure

; Main------------------------------------------------------------------
  Init()
  Main()

; End-------------------------------------------------------------------
End
User avatar
Stefan Schnell
User
User
Posts: 80
Joined: Wed May 07, 2003 2:53 pm
Location: Germany - Oberirsen
Contact:

How to connect a SAP® system with PureBasic - Step 5

Post by Stefan Schnell »

Now ABAP® tell what to do
In this step I will show how to register a server program and call a function from the SAP® system via ABAP®. At first we must define a RFC destination with the transaction code SM59 in the SAP® system. Take connection type T and in the tab Technical Settings activate the radio button Registered Server Program. In the Program ID type PBTESTPROGRAM and in the Gateway Options in Gateway Host localhost and in Gateway service sapgw00. Now we use the same arguments in our program via the function RfcAcceptExt. After the registering of our server program to the SAP® gateway we use the function RfcListen to hear the function calls. If a function is called, we look, with the function RfcGetName, about the name. If it is Z_TEST we use RfcGetData and RfcSendData to communicate with the calling ABAP® program. If you want, you can test the connection with the button connection test in SM59.

Hint
You must stop the your PureBasic server program with kill program.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  ; Constants-----------------------------------------------------------
    XIncludeFile "librfc32.constants.pbi"

    Enumeration
      #RFCLib
    EndEnumeration

  ; Structures----------------------------------------------------------
    XIncludeFile "librfc32.structures.pbi"

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected hRFC.l = 0
        Protected strCon.s = "-aPBTESTPROGRAM -glocalhost -xsapgw00"
        Protected rc = #RFC_RETRY
        Protected RET = #RFC_OK
        Protected FuncName.s = #NULL$
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      Exporting(0)\name = #Null
      Importing(0)\name = #Null
      Tables(0)\name = #Null

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = CallFunction(#RFCLib, "RfcAcceptExt", @strCon)
        ; Obsolet-------------------------------------------------------
        ;
        ;  RfcAcceptExt is obsolet, but RfcAccept do not work
        ;
        ; --------------------------------------------------------------

        If hRFC

          While rc = #RFC_RETRY Or rc = #RFC_OK
            Delay(32)
            rc = CallFunction(#RFCLib, "RfcListen", hRFC)
            Select rc
              Case #RFC_OK
                Debug("Get Call")
                rc = CallFunction(#RFCLib, "RfcGetName", hRFC, @FuncName)
                Select UCase(FuncName)
                  Case "Z_TEST"
                    Debug "Z_TEST"
                    CallFunction(#RFCLib, "RfcGetData", hRFC, _
                      @Importing(), @Tables())

                    CallFunction(#RFCLib, "RfcSendData", hRFC, _
                      @Exporting(), @Tables())
                EndSelect
            EndSelect
          Wend

          CallFunction(#RFCLib, "RfcClose", hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

  ; Main----------------------------------------------------------------
    Main()

; End-------------------------------------------------------------------
End
Now lets take a look at the ABAP program, which calls the PureBasic program.

Code: Select all

"-Begin-----------------------------------------------------------------

  REPORT  Z_DESTTEST.

    Call Function 'Z_TEST' Destination 'PBTESTPROGRAM'.

    If sy-subrc = 0.
      Write: / 'Done'.
    EndIf.

"-End-------------------------------------------------------------------
Here is another way to execute PureBasic functions with ABAP®. We register the PureBasic function with RfcInstallFunctionExt. The combination of RfcListen and RfcDispatch brings our function to execute.

Code: Select all

; Begin-----------------------------------------------------------------

  ; Directives----------------------------------------------------------
    $LPP
    EnableExplicit

  ; Constants-----------------------------------------------------------
    XIncludeFile "librfc32.constants.pbi"

    Enumeration
      #RFCLib
    EndEnumeration

  ; Variables-----------------------------------------------------------
    Global hRFC.l = 0

  ; Structures----------------------------------------------------------
    XIncludeFile "librfc32.structures.pbi"

  ; Procedure Z_TEST----------------------------------------------------
    Procedure Z_TEST()

      ; Variables-------------------------------------------------------
        Dim Exporting.RFC_PARAMETER(32)
        Dim Importing.RFC_PARAMETER(32)
        Dim Tables.RFC_TABLE(32)

      Exporting(0)\name = #Null
      Importing(0)\name = #Null
      Tables(0)\name = #Null

      CallFunction(#RFCLib, "RfcGetData", hRFC, @Importing(), _
        @Tables())

      Debug "Done from Z_TEST"

      CallFunction(#RFCLib, "RfcSendData", hRFC, @Exporting(), _
        @Tables())

      ProcedureReturn #RFC_OK
    EndProcedure

  ; Procedure Main------------------------------------------------------
    Procedure Main()

      ; Variables-------------------------------------------------------
        Protected strCon.s = "-aPBTESTPROGRAM -glocalhost -xsapgw00"
        Protected rc = #RFC_OK

      If OpenLibrary(#RFCLib, "librfc32.dll")

        hRFC = CallFunction(#RFCLib, "RfcAcceptExt", @strCon)

        If hRFC

          CallFunction(#RFCLib, "RfcInstallFunctionExt", hRFC, _
            @"Z_TEST", @Z_TEST(), @"Test function module from PB")

          While rc = #RFC_OK
            rc = #RFC_RETRY
            While rc = #RFC_RETRY
              Delay(32)
              rc = CallFunction(#RFCLib, "RfcListen", hRFC)
            Wend
            rc = CallFunction(#RFCLib, "RfcDispatch", hRFC)
          Wend

          CallFunction(#RFCLib, "RfcClose", hRFC)
        EndIf
        CloseLibrary(#RFCLib)
      EndIf

    EndProcedure

  ; Main----------------------------------------------------------------
    Main()

; End-------------------------------------------------------------------
End
dige
Addict
Addict
Posts: 1252
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: How to connect a SAP® system with PureBasic (Windows)

Post by dige »

I have no SAP System here, but very interessting stuff and good to
know that PB can connect to that system. I'll keep it in my mind,
thanks for sharing!
Tranquil
Addict
Addict
Posts: 950
Joined: Mon Apr 28, 2003 2:22 pm
Location: Europe

Re: How to connect a SAP® system with PureBasic (Windows)

Post by Tranquil »

VERY good work!! Thanks for posting!! Will surely come in handy some time! :D
Tranquil
Amundo
Enthusiast
Enthusiast
Posts: 191
Joined: Thu Feb 16, 2006 1:41 am
Location: New Zealand

Re: How to connect a SAP® system with PureBasic (Windows)

Post by Amundo »

Wow! Very good work, Stefan.

I have wondered about using PB with SAP, now I have no excuse!

Thanks!
Win8.1, PB5.x, okayish CPU, onboard video card, fuzzy monitor (or is that my eyesight?)
"When the facts change, I change my mind" - John Maynard Keynes
User avatar
Stefan Schnell
User
User
Posts: 80
Joined: Wed May 07, 2003 2:53 pm
Location: Germany - Oberirsen
Contact:

Re: A small addition

Post by Stefan Schnell »

Hello community,
SAP© stop the development of the classic RFC API with version 7.10. The new RFC library call SAP© NetWeaver® RFC API. It is totally restructured and offers new extended functionalities. The examples above work only with the classic RFC API. I test it with version 7.10. The examples do not work with SAP© NetWeaver® RFC.
Cheers
Stefan
Last edited by Stefan Schnell on Mon Sep 13, 2010 11:42 am, edited 1 time in total.
glops
User
User
Posts: 38
Joined: Wed Jan 16, 2008 12:53 pm
Location: France

Re: How to connect a SAP ® system with PureBasic (Windows)

Post by glops »

Thanks ! I already published some working codes using COMATE last year. It's a little more readable and easy to manage, imha. Will try your's when I have time !
ps: and works with SAP Netweaver as well !
Post Reply