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
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
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
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-------------------------------------------------------------------
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-------------------------------------------------------------------
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-------------------------------------------------------------------