nwrfc 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/README.rdoc +124 -120
- data/Rakefile +8 -8
- data/lib/nwrfc.rb +390 -389
- data/lib/nwrfc/datacontainer.rb +337 -337
- data/lib/nwrfc/nwerror.rb +39 -24
- data/lib/nwrfc/nwrfclib.rb +436 -436
- data/lib/nwrfc/server.rb +45 -45
- metadata +37 -59
data/lib/nwrfc/nwerror.rb
CHANGED
@@ -1,25 +1,40 @@
|
|
1
|
-
module NWRFC
|
2
|
-
|
3
|
-
class NWError < Exception
|
4
|
-
|
5
|
-
attr_reader :code, :group, :message, :class, :type, :number
|
6
|
-
|
7
|
-
# Instantiate Error object with a handle to an FFI::MemoryPointer
|
8
|
-
# to an NWRFCLib::RFCError object. The error object is analyzed so that
|
9
|
-
# when the caller intercepts it with Rescue, all the error details are
|
10
|
-
# available
|
11
|
-
def initialize(error)
|
12
|
-
@code = NWRFCLib::RFC_RC[error[:code]]
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
1
|
+
module NWRFC
|
2
|
+
|
3
|
+
class NWError < Exception
|
4
|
+
|
5
|
+
attr_reader :code, :group, :message, :class, :type, :number
|
6
|
+
|
7
|
+
# Instantiate Error object with a handle to an FFI::MemoryPointer
|
8
|
+
# to an NWRFCLib::RFCError object. The error object is analyzed so that
|
9
|
+
# when the caller intercepts it with Rescue, all the error details are
|
10
|
+
# available
|
11
|
+
def initialize(error)
|
12
|
+
@code = NWRFCLib::RFC_RC[error[:code]]
|
13
|
+
# In the event that the called function raised an exception, we must create a more specific
|
14
|
+
# error
|
15
|
+
raise(NWABAPException, error[:key].get_str) if @code == :RFC_ABAP_EXCEPTION
|
16
|
+
@group = NWRFCLib::RFC_ERROR_GROUP[error[:group]]
|
17
|
+
@message = error[:message].get_str
|
18
|
+
@type = error[:abapMsgType].get_str
|
19
|
+
@number = error[:abapMsgNumber].get_str
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
"#{@message} (code #{@code}, group #{@group}, type #{@type}, number #{@number})"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class NWABAPException < NWError
|
29
|
+
attr_reader :exception
|
30
|
+
def initialize(exception)
|
31
|
+
@exception = exception
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
"Function exception #{exception}"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
25
40
|
end
|
data/lib/nwrfc/nwrfclib.rb
CHANGED
@@ -1,436 +1,436 @@
|
|
1
|
-
# Author:: Martin Ceronio martin.ceronio@infosize.co.za
|
2
|
-
# Copyright:: Copyright (c) 2012 Martin Ceronio
|
3
|
-
# License:: MIT and/or Creative Commons Attribution-ShareAlike
|
4
|
-
# SAP, Netweaver, RFC and other names referred to in this code
|
5
|
-
# are, or may be registered trademarks and the property of SAP, AG
|
6
|
-
# No ownership over any of these is asserted by Martin Ceronio
|
7
|
-
|
8
|
-
require 'rubygems'
|
9
|
-
require 'ffi'
|
10
|
-
require 'iconv'
|
11
|
-
|
12
|
-
RUBY_VERSION_18 = RUBY_VERSION[0..2] == "1.8"
|
13
|
-
|
14
|
-
# Provide an alias for FFI::MemoryPointer#read_int to `read_uint` in 1.8
|
15
|
-
# See http://stackoverflow.com/questions/9035661/ruby-ffi-memorypointer-read-int-present-in-1-9-but-not-1-8
|
16
|
-
# Probably not good to interpret an unsigned int as an int, but we don't expect to use it for big values
|
17
|
-
# that could result in sign conversion
|
18
|
-
# FIXME - This must go! Replace with calls to get_* defined in FFI::MemoryPointer
|
19
|
-
if RUBY_VERSION_18
|
20
|
-
FFI::MemoryPointer.class_eval{ alias :read_uint :read_int}
|
21
|
-
end
|
22
|
-
|
23
|
-
# Enhancement to FFI::Pointer to be able to read a double-null terminated string,
|
24
|
-
# which would be returned e.g. by RfcGetVersion() in the SDK
|
25
|
-
# See http://stackoverflow.com/questions/9293307/ruby-ffi-ruby-1-8-reading-utf-16le-encoded-strings
|
26
|
-
module FFI
|
27
|
-
class Pointer
|
28
|
-
|
29
|
-
# Enhancement to FFI::Pointer to be able to read a double-null terminated string,
|
30
|
-
# which would be returned e.g. by RfcGetVersion() in the SDK
|
31
|
-
# See http://stackoverflow.com/questions/9293307/ruby-ffi-ruby-1-8-reading-utf-16le-encoded-strings
|
32
|
-
# It should be safe to call this on a Pointer within the context of the NW RFC SDK library,
|
33
|
-
# because all strings are supposed to be UTF-16LE encoded and double-null terminated
|
34
|
-
def read_string_dn(max=0)
|
35
|
-
cont_nullcount = 0
|
36
|
-
offset = 0
|
37
|
-
until cont_nullcount == 2
|
38
|
-
byte = get_bytes(offset,1)
|
39
|
-
cont_nullcount += 1 if byte == "\000"
|
40
|
-
cont_nullcount = 0 if byte != "\000"
|
41
|
-
offset += 1
|
42
|
-
end
|
43
|
-
get_bytes(0,offset+1)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
# Enhancement to the String class to put string values into double-null
|
49
|
-
# terminated UTF16 little endian encoded strings as required by the NW RFC
|
50
|
-
# SDK function, which should work on Linux and Windows (and maybe other
|
51
|
-
# architectures, though the plan is not to support them)
|
52
|
-
#String.class_eval{define_method(:cU){ Iconv.conv("UTF-16LE", "UTF8", self+"\0") }}
|
53
|
-
class String
|
54
|
-
|
55
|
-
# Convert string from UTF-8 to doudble-null terminated UTF-16LE string
|
56
|
-
def cU
|
57
|
-
NWRFCLib::Cutf8_to_utf16le.iconv(self+"\0")
|
58
|
-
end
|
59
|
-
|
60
|
-
# Convert string from UTF-16LE to UTF-8 and trim trailing whitespace
|
61
|
-
def uC
|
62
|
-
NWRFCLib::Cutf16le_to_utf8.iconv(self).strip
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
# Enhancement to FFI::StructLayout::CharArray to add a get_str method that changes the
|
68
|
-
# string value of the character array by enforcing encoding of UTF-16LE (as used in NW RFC SDK)
|
69
|
-
# and strips off blanks at the end to return a readable String
|
70
|
-
class FFI::StructLayout::CharArray
|
71
|
-
def get_str
|
72
|
-
NWRFCLib::Cutf16le_to_utf8.iconv(self.to_ptr.read_string(self.size)).strip
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Library wrapper around NW RFC SDK shared library using RUBY-FFI
|
77
|
-
module NWRFCLib
|
78
|
-
|
79
|
-
Cutf8_to_utf16le = Iconv.new("UTF-16LE", "UTF-8")
|
80
|
-
Cutf16le_to_utf8 = Iconv.new("UTF-8", "UTF-16LE")
|
81
|
-
|
82
|
-
extend FFI::Library
|
83
|
-
ffi_lib 'sapnwrfc'
|
84
|
-
|
85
|
-
# Multiplier for providing correct byte size for String passed to RFC library
|
86
|
-
#@todo Make platform-dependent size based on RUBY_PLATFORM
|
87
|
-
B_SIZE = 2
|
88
|
-
|
89
|
-
RFC_RC = enum(
|
90
|
-
:RFC_OK,
|
91
|
-
:RFC_COMMUNICATION_FAILURE,
|
92
|
-
:RFC_LOGON_FAILURE,
|
93
|
-
:RFC_ABAP_RUNTIME_FAILURE,
|
94
|
-
:RFC_ABAP_MESSAGE,
|
95
|
-
:RFC_ABAP_EXCEPTION,
|
96
|
-
:RFC_CLOSED,
|
97
|
-
:RFC_CANCELED,
|
98
|
-
:RFC_TIMEOUT,
|
99
|
-
:RFC_MEMORY_INSUFFICIENT,
|
100
|
-
:RFC_VERSION_MISMATCH,
|
101
|
-
:RFC_INVALID_PROTOCOL,
|
102
|
-
:RFC_SERIALIZATION_FAILURE,
|
103
|
-
:RFC_INVALID_HANDLE,
|
104
|
-
:RFC_RETRY,
|
105
|
-
:RFC_EXTERNAL_FAILURE,
|
106
|
-
:RFC_EXECUTED,
|
107
|
-
:RFC_NOT_FOUND,
|
108
|
-
:RFC_NOT_SUPPORTED,
|
109
|
-
:RFC_ILLEGAL_STATE,
|
110
|
-
:RFC_INVALID_PARAMETER,
|
111
|
-
:RFC_CODEPAGE_CONVERSION_FAILURE,
|
112
|
-
:RFC_CONVERSION_FAILURE,
|
113
|
-
:RFC_BUFFER_TOO_SMALL,
|
114
|
-
:RFC_TABLE_MOVE_BOF,
|
115
|
-
:RFC_TABLE_MOVE_EOF,
|
116
|
-
:RFC_UNKNOWN_ERROR
|
117
|
-
)
|
118
|
-
|
119
|
-
RFC_ERROR_GROUP = enum(
|
120
|
-
:OK,
|
121
|
-
:ABAP_APPLICATION_FAILURE,
|
122
|
-
:ABAP_RUNTIME_FAILURE,
|
123
|
-
:LOGON_FAILURE,
|
124
|
-
:COMMUNICATION_FAILURE,
|
125
|
-
:EXTERNAL_RUNTIME_FAILURE,
|
126
|
-
:EXTERNAL_APPLICATION_FAILURE
|
127
|
-
)
|
128
|
-
|
129
|
-
RFC_DIRECTION = enum(
|
130
|
-
:RFC_IMPORT, 1,
|
131
|
-
:RFC_EXPORT, 2,
|
132
|
-
:RFC_CHANGING, 3,
|
133
|
-
:RFC_TABLES, 7
|
134
|
-
)
|
135
|
-
|
136
|
-
RFC_TYPE = enum(
|
137
|
-
:RFCTYPE_CHAR , 0,
|
138
|
-
:RFCTYPE_DATE , 1,
|
139
|
-
:RFCTYPE_BCD , 2,
|
140
|
-
:RFCTYPE_TIME , 3,
|
141
|
-
:RFCTYPE_BYTE , 4,
|
142
|
-
:RFCTYPE_TABLE , 5,
|
143
|
-
:RFCTYPE_NUM , 6,
|
144
|
-
:RFCTYPE_FLOAT , 7,
|
145
|
-
:RFCTYPE_INT , 8,
|
146
|
-
:RFCTYPE_INT2 , 9,
|
147
|
-
:RFCTYPE_INT1 , 10,
|
148
|
-
:RFCTYPE_NULL , 14,
|
149
|
-
:RFCTYPE_ABAPOBJECT, 16,
|
150
|
-
:RFCTYPE_STRUCTURE , 17,
|
151
|
-
:RFCTYPE_DECF16 , 23,
|
152
|
-
:RFCTYPE_DECF34 , 24,
|
153
|
-
:RFCTYPE_XMLDATA , 28,
|
154
|
-
:RFCTYPE_STRING , 29,
|
155
|
-
:RFCTYPE_XSTRING , 30,
|
156
|
-
:RFCTYPE_BOX, 31,
|
157
|
-
:RFCTYPE_GENERIC_BOX, 32,
|
158
|
-
:_RFCTYPE_max_value
|
159
|
-
)
|
160
|
-
|
161
|
-
# Connection parameter wrapper (struct RFC_CONNECTION_PARAMETER in sapnwrfc.h)
|
162
|
-
class RFCConnParam < FFI::Struct
|
163
|
-
layout :name, :pointer,
|
164
|
-
:value, :pointer
|
165
|
-
end
|
166
|
-
|
167
|
-
# Connection Details (struct RFC_ATTRIBUTES in sapnwrfc.h)
|
168
|
-
class RFCConnection < FFI::Struct
|
169
|
-
layout :dest, [:char, (64+1)*B_SIZE],
|
170
|
-
:host, [:char, (100+1)*B_SIZE],
|
171
|
-
:partnerHost, [:char, (100+1)*B_SIZE],
|
172
|
-
:sysNumber, [:char, (2+1)*B_SIZE],
|
173
|
-
:sysId, [:char, (8+1)*B_SIZE],
|
174
|
-
:client, [:char, (3+1)*B_SIZE],
|
175
|
-
:user, [:char, (12+1)*B_SIZE],
|
176
|
-
:language, [:char, (2+1)*B_SIZE],
|
177
|
-
:trace, [:char, (1+1)*B_SIZE],
|
178
|
-
:isoLanguage, [:char, (2+1)*B_SIZE],
|
179
|
-
:codepage, [:char, (4+1)*B_SIZE],
|
180
|
-
:partnerCodepage, [:char, (4+1)*B_SIZE],
|
181
|
-
:rfcRole, [:char, (1+1)*B_SIZE],
|
182
|
-
:type, [:char, (1+1)*B_SIZE],
|
183
|
-
:partnerType, [:char, (1+1)*B_SIZE],
|
184
|
-
:rel, [:char, (4+1)*B_SIZE],
|
185
|
-
:partnerRel, [:char, (4+1)*B_SIZE],
|
186
|
-
:kernelRel, [:char, (4+1)*B_SIZE],
|
187
|
-
:cpicConvId, [:char, (8+1)*B_SIZE],
|
188
|
-
:progName, [:char, (128+1)*B_SIZE],
|
189
|
-
:reserved, [:char, (86+1)*B_SIZE]
|
190
|
-
end
|
191
|
-
|
192
|
-
# Error info wrapper (struct RFC_ERROR_INFO in sapnwrfc.h)
|
193
|
-
class RFCError < FFI::Struct
|
194
|
-
layout :code, :int,
|
195
|
-
:group, :int,
|
196
|
-
:key, [:char, (128)*B_SIZE],
|
197
|
-
:message, [:char, (512)*B_SIZE],
|
198
|
-
:abapMsgClass, [:char, (20+1)*B_SIZE],
|
199
|
-
:abapMsgType, [:char, (1+1)*B_SIZE],
|
200
|
-
:abapMsgNumber, [:char, (3+1)*B_SIZE],
|
201
|
-
:abapMsgV1, [:char, (50+1)*B_SIZE],
|
202
|
-
:abapMsgV2, [:char, (50+1)*B_SIZE],
|
203
|
-
:abapMsgV3, [:char, (50+1)*B_SIZE],
|
204
|
-
:abapMsgV4, [:char, (50+1)*B_SIZE]
|
205
|
-
end
|
206
|
-
|
207
|
-
# Function Parameter Description (struct RFC_PARAMETER_DESC in sapnwrfc.h)
|
208
|
-
class RFCFuncParam < FFI::Struct
|
209
|
-
layout :name, [:char, (30+1)*B_SIZE],
|
210
|
-
:type, :int, #enum RFCTYPE
|
211
|
-
:direction, :int, #enum RFC_DIRECTION
|
212
|
-
:nucLength, :uint,
|
213
|
-
:ucLength, :uint,
|
214
|
-
:decimals, :uint,
|
215
|
-
:typeDescHandle, :pointer, #RFC_TYPE_DESC_HANDLE
|
216
|
-
:defaultValue, [:char, (30+1)*B_SIZE], #RFC_PARAMETER_DEFVALUE
|
217
|
-
:parameterText, [:char, (79+1)*B_SIZE], #RFC_PARAMETER_TEXT
|
218
|
-
:optional, :uchar, #RFC_BYTE
|
219
|
-
:extendedDescription, :pointer
|
220
|
-
end
|
221
|
-
|
222
|
-
class RFCFieldDesc < FFI::Struct
|
223
|
-
layout :name, [:char, (30+1)*B_SIZE],
|
224
|
-
:type, :int, #enum RFCTYPE
|
225
|
-
:nucLength, :uint,
|
226
|
-
:nucOffset, :uint,
|
227
|
-
:ucLength, :uint,
|
228
|
-
:ucOffset, :uint,
|
229
|
-
:decimals, :uint,
|
230
|
-
:typeDescHandle, :pointer, #RFC_TYPE_DESC_HANDLE
|
231
|
-
:extendedDescription, :pointer
|
232
|
-
end
|
233
|
-
|
234
|
-
class RFCDataContainer < FFI::Struct
|
235
|
-
layout :handle, :pointer
|
236
|
-
end
|
237
|
-
|
238
|
-
# typedef :RFCDataContainer, RFCStructureHandle
|
239
|
-
# typedef :RFCDataContainer, RFCTableHandle
|
240
|
-
|
241
|
-
class RFC_FUNCTION_DESC_HANDLE < FFI::Struct
|
242
|
-
layout :handle, :pointer
|
243
|
-
end
|
244
|
-
|
245
|
-
class RFC_TYPE_DESC_HANDLE < FFI::Struct
|
246
|
-
layout :handle, :pointer
|
247
|
-
end
|
248
|
-
|
249
|
-
class DATA_CONTAINER_HANDLE < FFI::Struct
|
250
|
-
layout :handle, :pointer
|
251
|
-
end
|
252
|
-
|
253
|
-
class RFC_DECF16 < FFI::Union
|
254
|
-
layout :bytes, [:uchar, 8],
|
255
|
-
:align, :double
|
256
|
-
end
|
257
|
-
|
258
|
-
# class SAP_MAX_ALIGN_T < FFI::Union
|
259
|
-
# layout :align1, :long,
|
260
|
-
# :align2, :double,
|
261
|
-
# :align3, :pointer,
|
262
|
-
# :align4,
|
263
|
-
# end
|
264
|
-
|
265
|
-
# class RFC_DECF34 < FFI::Union
|
266
|
-
# layout :bytes, [:uchar, 16],
|
267
|
-
# :align, 16
|
268
|
-
# end
|
269
|
-
|
270
|
-
#############################################################################################################
|
271
|
-
# ATTACH FUNCTIONS
|
272
|
-
# The functions here were obtained by parsing content from the doxygen files from the documentation
|
273
|
-
# accompanying the NW RFC SDK, and were tweaked here and there afterward. Most of them are actually not
|
274
|
-
# yet used in our NWRFC library, so calling them may not work. For best results, consult sapnwrfc.h from
|
275
|
-
# the SDK
|
276
|
-
#############################################################################################################
|
277
|
-
# Callback for function server (function implementation)
|
278
|
-
callback :funcimpl, [:pointer, :pointer, :pointer], :int
|
279
|
-
|
280
|
-
# Function mappings
|
281
|
-
[
|
282
|
-
[:add_exception, :RfcAddException, [:pointer, :pointer, :pointer], :int],
|
283
|
-
[:add_function_desc, :RfcAddFunctionDesc, [:pointer, :pointer, :pointer], :int],
|
284
|
-
[:add_parameter, :RfcAddParameter, [:pointer, :pointer, :pointer], :int],
|
285
|
-
[:add_type_desc, :RfcAddTypeDesc, [:pointer, :pointer, :pointer], :int],
|
286
|
-
[:add_type_field, :RfcAddTypeField, [:pointer, :pointer, :pointer], :int],
|
287
|
-
# @method append_new_row(table_handle, error_handle)
|
288
|
-
# @returns FFI::Pointer pointer to structure of new row
|
289
|
-
# calls RfcAppendNewRow()
|
290
|
-
[:append_new_row, :RfcAppendNewRow, [:pointer, :pointer], :pointer],
|
291
|
-
# @method append_row(table_handle, structure, error_handle)
|
292
|
-
# @returns Integer RC
|
293
|
-
# calls RfcAppendRow()
|
294
|
-
[:append_row, :RfcAppendRow, [:pointer, :pointer, :pointer], :int],
|
295
|
-
[:clone_structure, :RfcCloneStructure, [:pointer, :pointer], :pointer],
|
296
|
-
[:clone_table, :RfcCloneTable, [:pointer, :pointer], :pointer],
|
297
|
-
[:close_connection, :RfcCloseConnection, [:pointer, :pointer], :int],
|
298
|
-
[:confirm_transaction, :RfcConfirmTransaction, [:pointer, :pointer], :int],
|
299
|
-
[:create_function, :RfcCreateFunction, [:pointer, :pointer], :pointer],
|
300
|
-
[:create_function_desc, :RfcCreateFunctionDesc, [:pointer, :pointer], :pointer],
|
301
|
-
[:create_structure, :RfcCreateStructure, [:pointer, :pointer], :pointer],
|
302
|
-
[:create_table, :RfcCreateTable, [:pointer, :pointer], :pointer],
|
303
|
-
[:create_transaction, :RfcCreateTransaction, [:pointer, :pointer, :pointer, :pointer], :pointer],
|
304
|
-
[:create_type_desc, :RfcCreateTypeDesc, [:pointer, :pointer], :pointer],
|
305
|
-
[:delete_all_rows, :RfcDeleteAllRows, [:pointer, :pointer], :int],
|
306
|
-
[:delete_current_row, :RfcDeleteCurrentRow, [:pointer, :pointer], :int],
|
307
|
-
[:describe_function, :RfcDescribeFunction, [:pointer, :pointer], :pointer],
|
308
|
-
[:describe_type, :RfcDescribeType, [:pointer, :pointer], :pointer],
|
309
|
-
[:destroy_function, :RfcDestroyFunction, [:pointer, :pointer], :int],
|
310
|
-
[:destroy_function_desc, :RfcDestroyFunctionDesc, [:pointer, :pointer], :int],
|
311
|
-
[:destroy_structure, :RfcDestroyStructure, [:pointer, :pointer], :int],
|
312
|
-
[:destroy_table, :RfcDestroyTable, [:pointer, :pointer], :int],
|
313
|
-
[:destroy_transaction, :RfcDestroyTransaction, [:pointer, :pointer], :int],
|
314
|
-
[:destroy_type_desc, :RfcDestroyTypeDesc, [:pointer, :pointer], :int],
|
315
|
-
[:enable_basxml, :RfcEnableBASXML, [:pointer, :pointer], :int],
|
316
|
-
[:get_bytes, :RfcGetBytes, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
317
|
-
[:get_cached_function_desc, :RfcGetCachedFunctionDesc, [:pointer, :pointer, :pointer], :pointer],
|
318
|
-
[:get_cached_type_desc, :RfcGetCachedTypeDesc, [:pointer, :pointer, :pointer], :pointer],
|
319
|
-
[:get_chars, :RfcGetChars, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
320
|
-
[:get_connection_attributes, :RfcGetConnectionAttributes, [:pointer, :pointer, :pointer], :int],
|
321
|
-
[:get_current_row, :RfcGetCurrentRow, [:pointer, :pointer], :pointer],
|
322
|
-
[:get_date, :RfcGetDate, [:pointer, :pointer, :pointer, :pointer], :int],
|
323
|
-
[:get_dec_f16, :RfcGetDecF16, [:pointer, :pointer, :pointer, :pointer], :int],
|
324
|
-
[:get_dec_f34, :RfcGetDecF34, [:pointer, :pointer, :pointer, :pointer], :int],
|
325
|
-
[:get_direction_as_string, :RfcGetDirectionAsString, [:pointer], :pointer],
|
326
|
-
[:get_exception_count, :RfcGetExceptionCount, [:pointer, :pointer, :pointer], :int],
|
327
|
-
[:get_exception_desc_by_index, :RfcGetExceptionDescByIndex, [:pointer, :uint, :pointer, :pointer], :int],
|
328
|
-
[:get_exception_desc_by_name, :RfcGetExceptionDescByName, [:pointer, :pointer, :pointer, :pointer], :int],
|
329
|
-
[:get_field_count, :RfcGetFieldCount, [:pointer, :pointer, :pointer], :int],
|
330
|
-
[:get_field_desc_by_index, :RfcGetFieldDescByIndex, [:pointer, :uint, :pointer, :pointer], :int],
|
331
|
-
[:get_field_desc_by_name, :RfcGetFieldDescByName, [:pointer, :pointer, :pointer, :pointer], :int],
|
332
|
-
[:get_float, :RfcGetFloat, [:pointer, :pointer, :pointer, :pointer], :int],
|
333
|
-
[:get_function_desc, :RfcGetFunctionDesc, [:pointer, :pointer, :pointer], :pointer],
|
334
|
-
[:get_function_name, :RfcGetFunctionName, [:pointer, :pointer, :pointer], :int],
|
335
|
-
[:get_int, :RfcGetInt, [:pointer, :pointer, :pointer, :pointer], :int],
|
336
|
-
[:get_int1, :RfcGetInt1, [:pointer, :pointer, :pointer, :pointer], :int],
|
337
|
-
[:get_int2, :RfcGetInt2, [:pointer, :pointer, :pointer, :pointer], :int],
|
338
|
-
[:get_num, :RfcGetNum, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
339
|
-
[:get_parameter_count, :RfcGetParameterCount, [:pointer, :pointer, :pointer], :int],
|
340
|
-
[:get_parameter_desc_by_index, :RfcGetParameterDescByIndex, [:pointer, :uint, :pointer, :pointer], :int],
|
341
|
-
[:get_parameter_desc_by_name, :RfcGetParameterDescByName, [:pointer, :pointer, :pointer, :pointer], :int],
|
342
|
-
[:get_partner_snc_key, :RfcGetPartnerSNCKey, [:pointer, :pointer, :pointer, :pointer], :int],
|
343
|
-
[:get_partner_snc_name, :RfcGetPartnerSNCName, [:pointer, :pointer, :uint, :pointer], :int],
|
344
|
-
[:get_partner_sso_ticket, :RfcGetPartnerSSOTicket, [:pointer, :pointer, :pointer, :pointer], :int],
|
345
|
-
[:get_rc_as_string, :RfcGetRcAsString, [:pointer], :pointer],
|
346
|
-
[:get_row_count, :RfcGetRowCount, [:pointer, :pointer, :pointer], :int],
|
347
|
-
[:get_string, :RfcGetString, [:pointer, :pointer, :pointer, :uint, :pointer, :pointer], :int],
|
348
|
-
[:get_string_length, :RfcGetStringLength, [:pointer, :pointer, :pointer, :pointer], :int],
|
349
|
-
[:get_structure, :RfcGetStructure, [:pointer, :pointer, :pointer, :pointer], :int],
|
350
|
-
[:get_table, :RfcGetTable, [:pointer, :pointer, :pointer, :pointer], :int],
|
351
|
-
[:get_time, :RfcGetTime, [:pointer, :pointer, :pointer, :pointer], :int],
|
352
|
-
[:get_transaction_id, :RfcGetTransactionID, [:pointer, :pointer, :pointer], :int],
|
353
|
-
[:get_type_as_string, :RfcGetTypeAsString, [:pointer], :pointer],
|
354
|
-
[:get_type_desc, :RfcGetTypeDesc, [:pointer, :pointer, :pointer], :pointer],
|
355
|
-
[:get_type_length, :RfcGetTypeLength, [:pointer, :pointer, :pointer, :pointer], :int],
|
356
|
-
[:get_type_name, :RfcGetTypeName, [:pointer, :pointer, :pointer], :int],
|
357
|
-
[:get_version, :RfcGetVersion, [:pointer, :pointer, :pointer], :pointer],
|
358
|
-
[:get_x_string, :RfcGetXString, [:pointer, :pointer, :pointer, :uint, :pointer, :pointer], :int],
|
359
|
-
[:init, :RfcInit, [:pointer], :int],
|
360
|
-
[:insert_new_row, :RfcInsertNewRow, [:pointer, :pointer], :pointer],
|
361
|
-
[:insert_row, :RfcInsertRow, [:pointer, :pointer, :pointer], :int],
|
362
|
-
[:install_generic_server_function, :RfcInstallGenericServerFunction, [:pointer, :pointer, :pointer], :int],
|
363
|
-
[:install_server_function, :RfcInstallServerFunction, [:pointer, :pointer, :funcimpl, :pointer], :int],
|
364
|
-
[:install_transaction_handlers, :RfcInstallTransactionHandlers, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int],
|
365
|
-
[:invoke, :RfcInvoke, [:pointer, :pointer, :pointer], :int],
|
366
|
-
[:invoke_in_transaction, :RfcInvokeInTransaction, [:pointer, :pointer, :pointer], :int],
|
367
|
-
[:is_basxml_supported, :RfcIsBASXMLSupported, [:pointer, :pointer, :pointer], :int],
|
368
|
-
#[:is_connection_handle_valid, :RfcIsConnectionHandleValid, [:pointer, :pointer, :pointer], :int],
|
369
|
-
[:is_parameter_active, :RfcIsParameterActive, [:pointer, :pointer, :pointer, :pointer], :int],
|
370
|
-
[:listen_and_dispatch, :RfcListenAndDispatch, [:pointer, :int, :pointer], :int],
|
371
|
-
[:move_to, :RfcMoveTo, [:pointer, :uint, :pointer], :int],
|
372
|
-
[:move_to_first_row, :RfcMoveToFirstRow, [:pointer, :pointer], :int],
|
373
|
-
[:move_to_last_row, :RfcMoveToLastRow, [:pointer, :pointer], :int],
|
374
|
-
[:move_to_next_row, :RfcMoveToNextRow, [:pointer, :pointer], :int],
|
375
|
-
[:move_to_previous_row, :RfcMoveToPreviousRow, [:pointer, :pointer], :int],
|
376
|
-
[:open_connection, :RfcOpenConnection, [:pointer, :uint, :pointer], :pointer],
|
377
|
-
[:ping, :RfcPing, [:pointer, :pointer], :int],
|
378
|
-
[:register_server, :RfcRegisterServer, [:pointer, :uint, :pointer], :pointer],
|
379
|
-
[:reload_ini_file, :RfcReloadIniFile, [:pointer], :int],
|
380
|
-
# [:remove_function_desc, :RfcRemoveFunctionDesc, [:pointer, :pointer, :pointer], :int],
|
381
|
-
# [:remove_type_desc, :RfcRemoveTypeDesc, [:pointer, :pointer, :pointer], :int],
|
382
|
-
[:reset_server_context, :RfcResetServerContext, [:pointer, :pointer], :int],
|
383
|
-
[:sapuc_to_utf8, :RfcSAPUCToUTF8, [:pointer, :uint, :pointer, :pointer, :pointer, :pointer], :int],
|
384
|
-
[:set_bytes, :RfcSetBytes, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
385
|
-
[:set_chars, :RfcSetChars, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
386
|
-
[:set_date, :RfcSetDate, [:pointer, :pointer, :pointer, :pointer], :int],
|
387
|
-
#[:set_dec_f16, :RfcSetDecF16, [:pointer, :pointer, :pointer, :pointer], :int],
|
388
|
-
[:set_dec_f16, :RfcSetDecF16, [:pointer, :pointer, RFC_DECF16.by_value, :pointer], :int],
|
389
|
-
[:set_dec_f34, :RfcSetDecF34, [:pointer, :pointer, :pointer, :pointer], :int],
|
390
|
-
[:set_float, :RfcSetFloat, [:pointer, :pointer, :double, :pointer], :int],
|
391
|
-
[:set_ini_path, :RfcSetIniPath, [:pointer, :pointer], :int],
|
392
|
-
[:set_int, :RfcSetInt, [:pointer, :pointer, :long, :pointer], :int],
|
393
|
-
[:set_int1, :RfcSetInt1, [:pointer, :pointer, :uint8, :pointer], :int],
|
394
|
-
[:set_int2, :RfcSetInt2, [:pointer, :pointer, :short, :pointer], :int],
|
395
|
-
[:set_num, :RfcSetNum, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
396
|
-
[:set_parameter_active, :RfcSetParameterActive, [:pointer, :pointer, :int, :pointer], :int],
|
397
|
-
[:set_string, :RfcSetString, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
398
|
-
[:set_structure, :RfcSetStructure, [:pointer, :pointer, :pointer, :pointer], :int],
|
399
|
-
[:set_table, :RfcSetTable, [:pointer, :pointer, :pointer, :pointer], :int],
|
400
|
-
[:set_time, :RfcSetTime, [:pointer, :pointer, :pointer, :pointer], :int],
|
401
|
-
#[:set_trace_dir, :RfcSetTraceDir, [:pointer, :pointer], :int],
|
402
|
-
#[:set_trace_encoding, :RfcSetTraceEncoding, [:pointer, :pointer], :int],
|
403
|
-
#[:set_trace_level, :RfcSetTraceLevel, [:pointer, :pointer, :uint, :pointer], :int],
|
404
|
-
[:set_type_length, :RfcSetTypeLength, [:pointer, :uint, :uint, :pointer], :int],
|
405
|
-
[:set_x_string, :RfcSetXString, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
406
|
-
[:snc_key_to_name, :RfcSNCKeyToName, [:pointer, :pointer, :uint, :pointer, :uint, :pointer], :int],
|
407
|
-
[:snc_name_to_key, :RfcSNCNameToKey, [:pointer, :pointer, :pointer, :pointer, :pointer], :int],
|
408
|
-
[:start_server, :RfcStartServer, [:int, :pointer, :pointer, :uint, :pointer], :pointer],
|
409
|
-
[:submit_transaction, :RfcSubmitTransaction, [:pointer, :pointer], :int],
|
410
|
-
[:utf8_to_sapuc, :RfcUTF8ToSAPUC, [:pointer, :uint, :pointer, :pointer, :pointer, :pointer], :int]
|
411
|
-
].each{|funcsig|
|
412
|
-
attach_function(funcsig[0], funcsig[1], funcsig[2], funcsig[3])
|
413
|
-
}
|
414
|
-
|
415
|
-
# Take Hash of connection parameters and returns FFI pointer to an array
|
416
|
-
# for passing to connection
|
417
|
-
# ---
|
418
|
-
# TODO - Ideally, this method should live in nwrfc.rb
|
419
|
-
def NWRFCLib.make_conn_params(params) #https://github.com/ffi/ffi/wiki/Structs
|
420
|
-
par = FFI::MemoryPointer.new(RFCConnParam, params.length)
|
421
|
-
pars = params.length.times.collect do |i|
|
422
|
-
RFCConnParam.new(par + i * RFCConnParam.size)
|
423
|
-
end
|
424
|
-
#TODO Optimize this method
|
425
|
-
tpar = params.to_a
|
426
|
-
params.length.times do |n|
|
427
|
-
# str = (tpar[n][0].to_s + "\0").encode("UTF-16LE")
|
428
|
-
pars[n][:name] = FFI::MemoryPointer.from_string(tpar[n][0].to_s.cU)
|
429
|
-
# str = (tpar[n][1].to_s + "\0").encode("UTF-16LE")
|
430
|
-
# str = str.encode("UTF-16LE")
|
431
|
-
pars[n][:value] = FFI::MemoryPointer.from_string(tpar[n][1].to_s.cU)
|
432
|
-
end
|
433
|
-
par
|
434
|
-
end
|
435
|
-
|
436
|
-
end
|
1
|
+
# Author:: Martin Ceronio martin.ceronio@infosize.co.za
|
2
|
+
# Copyright:: Copyright (c) 2012 Martin Ceronio
|
3
|
+
# License:: MIT and/or Creative Commons Attribution-ShareAlike
|
4
|
+
# SAP, Netweaver, RFC and other names referred to in this code
|
5
|
+
# are, or may be registered trademarks and the property of SAP, AG
|
6
|
+
# No ownership over any of these is asserted by Martin Ceronio
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'ffi'
|
10
|
+
require 'iconv'
|
11
|
+
|
12
|
+
RUBY_VERSION_18 = RUBY_VERSION[0..2] == "1.8"
|
13
|
+
|
14
|
+
# Provide an alias for FFI::MemoryPointer#read_int to `read_uint` in 1.8
|
15
|
+
# See http://stackoverflow.com/questions/9035661/ruby-ffi-memorypointer-read-int-present-in-1-9-but-not-1-8
|
16
|
+
# Probably not good to interpret an unsigned int as an int, but we don't expect to use it for big values
|
17
|
+
# that could result in sign conversion
|
18
|
+
# FIXME - This must go! Replace with calls to get_* defined in FFI::MemoryPointer
|
19
|
+
if RUBY_VERSION_18
|
20
|
+
FFI::MemoryPointer.class_eval{ alias :read_uint :read_int}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Enhancement to FFI::Pointer to be able to read a double-null terminated string,
|
24
|
+
# which would be returned e.g. by RfcGetVersion() in the SDK
|
25
|
+
# See http://stackoverflow.com/questions/9293307/ruby-ffi-ruby-1-8-reading-utf-16le-encoded-strings
|
26
|
+
module FFI
|
27
|
+
class Pointer
|
28
|
+
|
29
|
+
# Enhancement to FFI::Pointer to be able to read a double-null terminated string,
|
30
|
+
# which would be returned e.g. by RfcGetVersion() in the SDK
|
31
|
+
# See http://stackoverflow.com/questions/9293307/ruby-ffi-ruby-1-8-reading-utf-16le-encoded-strings
|
32
|
+
# It should be safe to call this on a Pointer within the context of the NW RFC SDK library,
|
33
|
+
# because all strings are supposed to be UTF-16LE encoded and double-null terminated
|
34
|
+
def read_string_dn(max=0)
|
35
|
+
cont_nullcount = 0
|
36
|
+
offset = 0
|
37
|
+
until cont_nullcount == 2
|
38
|
+
byte = get_bytes(offset,1)
|
39
|
+
cont_nullcount += 1 if byte == "\000"
|
40
|
+
cont_nullcount = 0 if byte != "\000"
|
41
|
+
offset += 1
|
42
|
+
end
|
43
|
+
get_bytes(0,offset+1)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Enhancement to the String class to put string values into double-null
|
49
|
+
# terminated UTF16 little endian encoded strings as required by the NW RFC
|
50
|
+
# SDK function, which should work on Linux and Windows (and maybe other
|
51
|
+
# architectures, though the plan is not to support them)
|
52
|
+
#String.class_eval{define_method(:cU){ Iconv.conv("UTF-16LE", "UTF8", self+"\0") }}
|
53
|
+
class String
|
54
|
+
|
55
|
+
# Convert string from UTF-8 to doudble-null terminated UTF-16LE string
|
56
|
+
def cU
|
57
|
+
NWRFCLib::Cutf8_to_utf16le.iconv(self+"\0")
|
58
|
+
end
|
59
|
+
|
60
|
+
# Convert string from UTF-16LE to UTF-8 and trim trailing whitespace
|
61
|
+
def uC
|
62
|
+
NWRFCLib::Cutf16le_to_utf8.iconv(self).strip
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# Enhancement to FFI::StructLayout::CharArray to add a get_str method that changes the
|
68
|
+
# string value of the character array by enforcing encoding of UTF-16LE (as used in NW RFC SDK)
|
69
|
+
# and strips off blanks at the end to return a readable String
|
70
|
+
class FFI::StructLayout::CharArray
|
71
|
+
def get_str
|
72
|
+
NWRFCLib::Cutf16le_to_utf8.iconv(self.to_ptr.read_string(self.size)).strip
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Library wrapper around NW RFC SDK shared library using RUBY-FFI
|
77
|
+
module NWRFCLib
|
78
|
+
|
79
|
+
Cutf8_to_utf16le = Iconv.new("UTF-16LE", "UTF-8")
|
80
|
+
Cutf16le_to_utf8 = Iconv.new("UTF-8", "UTF-16LE")
|
81
|
+
|
82
|
+
extend FFI::Library
|
83
|
+
ffi_lib 'sapnwrfc'
|
84
|
+
|
85
|
+
# Multiplier for providing correct byte size for String passed to RFC library
|
86
|
+
#@todo Make platform-dependent size based on RUBY_PLATFORM
|
87
|
+
B_SIZE = 2
|
88
|
+
|
89
|
+
RFC_RC = enum(
|
90
|
+
:RFC_OK,
|
91
|
+
:RFC_COMMUNICATION_FAILURE,
|
92
|
+
:RFC_LOGON_FAILURE,
|
93
|
+
:RFC_ABAP_RUNTIME_FAILURE,
|
94
|
+
:RFC_ABAP_MESSAGE,
|
95
|
+
:RFC_ABAP_EXCEPTION,
|
96
|
+
:RFC_CLOSED,
|
97
|
+
:RFC_CANCELED,
|
98
|
+
:RFC_TIMEOUT,
|
99
|
+
:RFC_MEMORY_INSUFFICIENT,
|
100
|
+
:RFC_VERSION_MISMATCH,
|
101
|
+
:RFC_INVALID_PROTOCOL,
|
102
|
+
:RFC_SERIALIZATION_FAILURE,
|
103
|
+
:RFC_INVALID_HANDLE,
|
104
|
+
:RFC_RETRY,
|
105
|
+
:RFC_EXTERNAL_FAILURE,
|
106
|
+
:RFC_EXECUTED,
|
107
|
+
:RFC_NOT_FOUND,
|
108
|
+
:RFC_NOT_SUPPORTED,
|
109
|
+
:RFC_ILLEGAL_STATE,
|
110
|
+
:RFC_INVALID_PARAMETER,
|
111
|
+
:RFC_CODEPAGE_CONVERSION_FAILURE,
|
112
|
+
:RFC_CONVERSION_FAILURE,
|
113
|
+
:RFC_BUFFER_TOO_SMALL,
|
114
|
+
:RFC_TABLE_MOVE_BOF,
|
115
|
+
:RFC_TABLE_MOVE_EOF,
|
116
|
+
:RFC_UNKNOWN_ERROR
|
117
|
+
)
|
118
|
+
|
119
|
+
RFC_ERROR_GROUP = enum(
|
120
|
+
:OK,
|
121
|
+
:ABAP_APPLICATION_FAILURE,
|
122
|
+
:ABAP_RUNTIME_FAILURE,
|
123
|
+
:LOGON_FAILURE,
|
124
|
+
:COMMUNICATION_FAILURE,
|
125
|
+
:EXTERNAL_RUNTIME_FAILURE,
|
126
|
+
:EXTERNAL_APPLICATION_FAILURE
|
127
|
+
)
|
128
|
+
|
129
|
+
RFC_DIRECTION = enum(
|
130
|
+
:RFC_IMPORT, 1,
|
131
|
+
:RFC_EXPORT, 2,
|
132
|
+
:RFC_CHANGING, 3,
|
133
|
+
:RFC_TABLES, 7
|
134
|
+
)
|
135
|
+
|
136
|
+
RFC_TYPE = enum(
|
137
|
+
:RFCTYPE_CHAR , 0,
|
138
|
+
:RFCTYPE_DATE , 1,
|
139
|
+
:RFCTYPE_BCD , 2,
|
140
|
+
:RFCTYPE_TIME , 3,
|
141
|
+
:RFCTYPE_BYTE , 4,
|
142
|
+
:RFCTYPE_TABLE , 5,
|
143
|
+
:RFCTYPE_NUM , 6,
|
144
|
+
:RFCTYPE_FLOAT , 7,
|
145
|
+
:RFCTYPE_INT , 8,
|
146
|
+
:RFCTYPE_INT2 , 9,
|
147
|
+
:RFCTYPE_INT1 , 10,
|
148
|
+
:RFCTYPE_NULL , 14,
|
149
|
+
:RFCTYPE_ABAPOBJECT, 16,
|
150
|
+
:RFCTYPE_STRUCTURE , 17,
|
151
|
+
:RFCTYPE_DECF16 , 23,
|
152
|
+
:RFCTYPE_DECF34 , 24,
|
153
|
+
:RFCTYPE_XMLDATA , 28,
|
154
|
+
:RFCTYPE_STRING , 29,
|
155
|
+
:RFCTYPE_XSTRING , 30,
|
156
|
+
:RFCTYPE_BOX, 31,
|
157
|
+
:RFCTYPE_GENERIC_BOX, 32,
|
158
|
+
:_RFCTYPE_max_value
|
159
|
+
)
|
160
|
+
|
161
|
+
# Connection parameter wrapper (struct RFC_CONNECTION_PARAMETER in sapnwrfc.h)
|
162
|
+
class RFCConnParam < FFI::Struct
|
163
|
+
layout :name, :pointer,
|
164
|
+
:value, :pointer
|
165
|
+
end
|
166
|
+
|
167
|
+
# Connection Details (struct RFC_ATTRIBUTES in sapnwrfc.h)
|
168
|
+
class RFCConnection < FFI::Struct
|
169
|
+
layout :dest, [:char, (64+1)*B_SIZE],
|
170
|
+
:host, [:char, (100+1)*B_SIZE],
|
171
|
+
:partnerHost, [:char, (100+1)*B_SIZE],
|
172
|
+
:sysNumber, [:char, (2+1)*B_SIZE],
|
173
|
+
:sysId, [:char, (8+1)*B_SIZE],
|
174
|
+
:client, [:char, (3+1)*B_SIZE],
|
175
|
+
:user, [:char, (12+1)*B_SIZE],
|
176
|
+
:language, [:char, (2+1)*B_SIZE],
|
177
|
+
:trace, [:char, (1+1)*B_SIZE],
|
178
|
+
:isoLanguage, [:char, (2+1)*B_SIZE],
|
179
|
+
:codepage, [:char, (4+1)*B_SIZE],
|
180
|
+
:partnerCodepage, [:char, (4+1)*B_SIZE],
|
181
|
+
:rfcRole, [:char, (1+1)*B_SIZE],
|
182
|
+
:type, [:char, (1+1)*B_SIZE],
|
183
|
+
:partnerType, [:char, (1+1)*B_SIZE],
|
184
|
+
:rel, [:char, (4+1)*B_SIZE],
|
185
|
+
:partnerRel, [:char, (4+1)*B_SIZE],
|
186
|
+
:kernelRel, [:char, (4+1)*B_SIZE],
|
187
|
+
:cpicConvId, [:char, (8+1)*B_SIZE],
|
188
|
+
:progName, [:char, (128+1)*B_SIZE],
|
189
|
+
:reserved, [:char, (86+1)*B_SIZE]
|
190
|
+
end
|
191
|
+
|
192
|
+
# Error info wrapper (struct RFC_ERROR_INFO in sapnwrfc.h)
|
193
|
+
class RFCError < FFI::Struct
|
194
|
+
layout :code, :int,
|
195
|
+
:group, :int,
|
196
|
+
:key, [:char, (128)*B_SIZE],
|
197
|
+
:message, [:char, (512)*B_SIZE],
|
198
|
+
:abapMsgClass, [:char, (20+1)*B_SIZE],
|
199
|
+
:abapMsgType, [:char, (1+1)*B_SIZE],
|
200
|
+
:abapMsgNumber, [:char, (3+1)*B_SIZE],
|
201
|
+
:abapMsgV1, [:char, (50+1)*B_SIZE],
|
202
|
+
:abapMsgV2, [:char, (50+1)*B_SIZE],
|
203
|
+
:abapMsgV3, [:char, (50+1)*B_SIZE],
|
204
|
+
:abapMsgV4, [:char, (50+1)*B_SIZE]
|
205
|
+
end
|
206
|
+
|
207
|
+
# Function Parameter Description (struct RFC_PARAMETER_DESC in sapnwrfc.h)
|
208
|
+
class RFCFuncParam < FFI::Struct
|
209
|
+
layout :name, [:char, (30+1)*B_SIZE],
|
210
|
+
:type, :int, #enum RFCTYPE
|
211
|
+
:direction, :int, #enum RFC_DIRECTION
|
212
|
+
:nucLength, :uint,
|
213
|
+
:ucLength, :uint,
|
214
|
+
:decimals, :uint,
|
215
|
+
:typeDescHandle, :pointer, #RFC_TYPE_DESC_HANDLE
|
216
|
+
:defaultValue, [:char, (30+1)*B_SIZE], #RFC_PARAMETER_DEFVALUE
|
217
|
+
:parameterText, [:char, (79+1)*B_SIZE], #RFC_PARAMETER_TEXT
|
218
|
+
:optional, :uchar, #RFC_BYTE
|
219
|
+
:extendedDescription, :pointer
|
220
|
+
end
|
221
|
+
|
222
|
+
class RFCFieldDesc < FFI::Struct
|
223
|
+
layout :name, [:char, (30+1)*B_SIZE],
|
224
|
+
:type, :int, #enum RFCTYPE
|
225
|
+
:nucLength, :uint,
|
226
|
+
:nucOffset, :uint,
|
227
|
+
:ucLength, :uint,
|
228
|
+
:ucOffset, :uint,
|
229
|
+
:decimals, :uint,
|
230
|
+
:typeDescHandle, :pointer, #RFC_TYPE_DESC_HANDLE
|
231
|
+
:extendedDescription, :pointer
|
232
|
+
end
|
233
|
+
|
234
|
+
class RFCDataContainer < FFI::Struct
|
235
|
+
layout :handle, :pointer
|
236
|
+
end
|
237
|
+
|
238
|
+
# typedef :RFCDataContainer, RFCStructureHandle
|
239
|
+
# typedef :RFCDataContainer, RFCTableHandle
|
240
|
+
|
241
|
+
class RFC_FUNCTION_DESC_HANDLE < FFI::Struct
|
242
|
+
layout :handle, :pointer
|
243
|
+
end
|
244
|
+
|
245
|
+
class RFC_TYPE_DESC_HANDLE < FFI::Struct
|
246
|
+
layout :handle, :pointer
|
247
|
+
end
|
248
|
+
|
249
|
+
class DATA_CONTAINER_HANDLE < FFI::Struct
|
250
|
+
layout :handle, :pointer
|
251
|
+
end
|
252
|
+
|
253
|
+
class RFC_DECF16 < FFI::Union
|
254
|
+
layout :bytes, [:uchar, 8],
|
255
|
+
:align, :double
|
256
|
+
end
|
257
|
+
|
258
|
+
# class SAP_MAX_ALIGN_T < FFI::Union
|
259
|
+
# layout :align1, :long,
|
260
|
+
# :align2, :double,
|
261
|
+
# :align3, :pointer,
|
262
|
+
# :align4,
|
263
|
+
# end
|
264
|
+
|
265
|
+
# class RFC_DECF34 < FFI::Union
|
266
|
+
# layout :bytes, [:uchar, 16],
|
267
|
+
# :align, 16
|
268
|
+
# end
|
269
|
+
|
270
|
+
#############################################################################################################
|
271
|
+
# ATTACH FUNCTIONS
|
272
|
+
# The functions here were obtained by parsing content from the doxygen files from the documentation
|
273
|
+
# accompanying the NW RFC SDK, and were tweaked here and there afterward. Most of them are actually not
|
274
|
+
# yet used in our NWRFC library, so calling them may not work. For best results, consult sapnwrfc.h from
|
275
|
+
# the SDK
|
276
|
+
#############################################################################################################
|
277
|
+
# Callback for function server (function implementation)
|
278
|
+
callback :funcimpl, [:pointer, :pointer, :pointer], :int
|
279
|
+
|
280
|
+
# Function mappings
|
281
|
+
[
|
282
|
+
[:add_exception, :RfcAddException, [:pointer, :pointer, :pointer], :int],
|
283
|
+
[:add_function_desc, :RfcAddFunctionDesc, [:pointer, :pointer, :pointer], :int],
|
284
|
+
[:add_parameter, :RfcAddParameter, [:pointer, :pointer, :pointer], :int],
|
285
|
+
[:add_type_desc, :RfcAddTypeDesc, [:pointer, :pointer, :pointer], :int],
|
286
|
+
[:add_type_field, :RfcAddTypeField, [:pointer, :pointer, :pointer], :int],
|
287
|
+
# @method append_new_row(table_handle, error_handle)
|
288
|
+
# @returns FFI::Pointer pointer to structure of new row
|
289
|
+
# calls RfcAppendNewRow()
|
290
|
+
[:append_new_row, :RfcAppendNewRow, [:pointer, :pointer], :pointer],
|
291
|
+
# @method append_row(table_handle, structure, error_handle)
|
292
|
+
# @returns Integer RC
|
293
|
+
# calls RfcAppendRow()
|
294
|
+
[:append_row, :RfcAppendRow, [:pointer, :pointer, :pointer], :int],
|
295
|
+
[:clone_structure, :RfcCloneStructure, [:pointer, :pointer], :pointer],
|
296
|
+
[:clone_table, :RfcCloneTable, [:pointer, :pointer], :pointer],
|
297
|
+
[:close_connection, :RfcCloseConnection, [:pointer, :pointer], :int],
|
298
|
+
[:confirm_transaction, :RfcConfirmTransaction, [:pointer, :pointer], :int],
|
299
|
+
[:create_function, :RfcCreateFunction, [:pointer, :pointer], :pointer],
|
300
|
+
[:create_function_desc, :RfcCreateFunctionDesc, [:pointer, :pointer], :pointer],
|
301
|
+
[:create_structure, :RfcCreateStructure, [:pointer, :pointer], :pointer],
|
302
|
+
[:create_table, :RfcCreateTable, [:pointer, :pointer], :pointer],
|
303
|
+
[:create_transaction, :RfcCreateTransaction, [:pointer, :pointer, :pointer, :pointer], :pointer],
|
304
|
+
[:create_type_desc, :RfcCreateTypeDesc, [:pointer, :pointer], :pointer],
|
305
|
+
[:delete_all_rows, :RfcDeleteAllRows, [:pointer, :pointer], :int],
|
306
|
+
[:delete_current_row, :RfcDeleteCurrentRow, [:pointer, :pointer], :int],
|
307
|
+
[:describe_function, :RfcDescribeFunction, [:pointer, :pointer], :pointer],
|
308
|
+
[:describe_type, :RfcDescribeType, [:pointer, :pointer], :pointer],
|
309
|
+
[:destroy_function, :RfcDestroyFunction, [:pointer, :pointer], :int],
|
310
|
+
[:destroy_function_desc, :RfcDestroyFunctionDesc, [:pointer, :pointer], :int],
|
311
|
+
[:destroy_structure, :RfcDestroyStructure, [:pointer, :pointer], :int],
|
312
|
+
[:destroy_table, :RfcDestroyTable, [:pointer, :pointer], :int],
|
313
|
+
[:destroy_transaction, :RfcDestroyTransaction, [:pointer, :pointer], :int],
|
314
|
+
[:destroy_type_desc, :RfcDestroyTypeDesc, [:pointer, :pointer], :int],
|
315
|
+
[:enable_basxml, :RfcEnableBASXML, [:pointer, :pointer], :int],
|
316
|
+
[:get_bytes, :RfcGetBytes, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
317
|
+
[:get_cached_function_desc, :RfcGetCachedFunctionDesc, [:pointer, :pointer, :pointer], :pointer],
|
318
|
+
[:get_cached_type_desc, :RfcGetCachedTypeDesc, [:pointer, :pointer, :pointer], :pointer],
|
319
|
+
[:get_chars, :RfcGetChars, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
320
|
+
[:get_connection_attributes, :RfcGetConnectionAttributes, [:pointer, :pointer, :pointer], :int],
|
321
|
+
[:get_current_row, :RfcGetCurrentRow, [:pointer, :pointer], :pointer],
|
322
|
+
[:get_date, :RfcGetDate, [:pointer, :pointer, :pointer, :pointer], :int],
|
323
|
+
[:get_dec_f16, :RfcGetDecF16, [:pointer, :pointer, :pointer, :pointer], :int],
|
324
|
+
[:get_dec_f34, :RfcGetDecF34, [:pointer, :pointer, :pointer, :pointer], :int],
|
325
|
+
[:get_direction_as_string, :RfcGetDirectionAsString, [:pointer], :pointer],
|
326
|
+
[:get_exception_count, :RfcGetExceptionCount, [:pointer, :pointer, :pointer], :int],
|
327
|
+
[:get_exception_desc_by_index, :RfcGetExceptionDescByIndex, [:pointer, :uint, :pointer, :pointer], :int],
|
328
|
+
[:get_exception_desc_by_name, :RfcGetExceptionDescByName, [:pointer, :pointer, :pointer, :pointer], :int],
|
329
|
+
[:get_field_count, :RfcGetFieldCount, [:pointer, :pointer, :pointer], :int],
|
330
|
+
[:get_field_desc_by_index, :RfcGetFieldDescByIndex, [:pointer, :uint, :pointer, :pointer], :int],
|
331
|
+
[:get_field_desc_by_name, :RfcGetFieldDescByName, [:pointer, :pointer, :pointer, :pointer], :int],
|
332
|
+
[:get_float, :RfcGetFloat, [:pointer, :pointer, :pointer, :pointer], :int],
|
333
|
+
[:get_function_desc, :RfcGetFunctionDesc, [:pointer, :pointer, :pointer], :pointer],
|
334
|
+
[:get_function_name, :RfcGetFunctionName, [:pointer, :pointer, :pointer], :int],
|
335
|
+
[:get_int, :RfcGetInt, [:pointer, :pointer, :pointer, :pointer], :int],
|
336
|
+
[:get_int1, :RfcGetInt1, [:pointer, :pointer, :pointer, :pointer], :int],
|
337
|
+
[:get_int2, :RfcGetInt2, [:pointer, :pointer, :pointer, :pointer], :int],
|
338
|
+
[:get_num, :RfcGetNum, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
339
|
+
[:get_parameter_count, :RfcGetParameterCount, [:pointer, :pointer, :pointer], :int],
|
340
|
+
[:get_parameter_desc_by_index, :RfcGetParameterDescByIndex, [:pointer, :uint, :pointer, :pointer], :int],
|
341
|
+
[:get_parameter_desc_by_name, :RfcGetParameterDescByName, [:pointer, :pointer, :pointer, :pointer], :int],
|
342
|
+
[:get_partner_snc_key, :RfcGetPartnerSNCKey, [:pointer, :pointer, :pointer, :pointer], :int],
|
343
|
+
[:get_partner_snc_name, :RfcGetPartnerSNCName, [:pointer, :pointer, :uint, :pointer], :int],
|
344
|
+
[:get_partner_sso_ticket, :RfcGetPartnerSSOTicket, [:pointer, :pointer, :pointer, :pointer], :int],
|
345
|
+
[:get_rc_as_string, :RfcGetRcAsString, [:pointer], :pointer],
|
346
|
+
[:get_row_count, :RfcGetRowCount, [:pointer, :pointer, :pointer], :int],
|
347
|
+
[:get_string, :RfcGetString, [:pointer, :pointer, :pointer, :uint, :pointer, :pointer], :int],
|
348
|
+
[:get_string_length, :RfcGetStringLength, [:pointer, :pointer, :pointer, :pointer], :int],
|
349
|
+
[:get_structure, :RfcGetStructure, [:pointer, :pointer, :pointer, :pointer], :int],
|
350
|
+
[:get_table, :RfcGetTable, [:pointer, :pointer, :pointer, :pointer], :int],
|
351
|
+
[:get_time, :RfcGetTime, [:pointer, :pointer, :pointer, :pointer], :int],
|
352
|
+
[:get_transaction_id, :RfcGetTransactionID, [:pointer, :pointer, :pointer], :int],
|
353
|
+
[:get_type_as_string, :RfcGetTypeAsString, [:pointer], :pointer],
|
354
|
+
[:get_type_desc, :RfcGetTypeDesc, [:pointer, :pointer, :pointer], :pointer],
|
355
|
+
[:get_type_length, :RfcGetTypeLength, [:pointer, :pointer, :pointer, :pointer], :int],
|
356
|
+
[:get_type_name, :RfcGetTypeName, [:pointer, :pointer, :pointer], :int],
|
357
|
+
[:get_version, :RfcGetVersion, [:pointer, :pointer, :pointer], :pointer],
|
358
|
+
[:get_x_string, :RfcGetXString, [:pointer, :pointer, :pointer, :uint, :pointer, :pointer], :int],
|
359
|
+
[:init, :RfcInit, [:pointer], :int],
|
360
|
+
[:insert_new_row, :RfcInsertNewRow, [:pointer, :pointer], :pointer],
|
361
|
+
[:insert_row, :RfcInsertRow, [:pointer, :pointer, :pointer], :int],
|
362
|
+
[:install_generic_server_function, :RfcInstallGenericServerFunction, [:pointer, :pointer, :pointer], :int],
|
363
|
+
[:install_server_function, :RfcInstallServerFunction, [:pointer, :pointer, :funcimpl, :pointer], :int],
|
364
|
+
[:install_transaction_handlers, :RfcInstallTransactionHandlers, [:pointer, :pointer, :pointer, :pointer, :pointer, :pointer], :int],
|
365
|
+
[:invoke, :RfcInvoke, [:pointer, :pointer, :pointer], :int],
|
366
|
+
[:invoke_in_transaction, :RfcInvokeInTransaction, [:pointer, :pointer, :pointer], :int],
|
367
|
+
[:is_basxml_supported, :RfcIsBASXMLSupported, [:pointer, :pointer, :pointer], :int],
|
368
|
+
#[:is_connection_handle_valid, :RfcIsConnectionHandleValid, [:pointer, :pointer, :pointer], :int],
|
369
|
+
[:is_parameter_active, :RfcIsParameterActive, [:pointer, :pointer, :pointer, :pointer], :int],
|
370
|
+
[:listen_and_dispatch, :RfcListenAndDispatch, [:pointer, :int, :pointer], :int],
|
371
|
+
[:move_to, :RfcMoveTo, [:pointer, :uint, :pointer], :int],
|
372
|
+
[:move_to_first_row, :RfcMoveToFirstRow, [:pointer, :pointer], :int],
|
373
|
+
[:move_to_last_row, :RfcMoveToLastRow, [:pointer, :pointer], :int],
|
374
|
+
[:move_to_next_row, :RfcMoveToNextRow, [:pointer, :pointer], :int],
|
375
|
+
[:move_to_previous_row, :RfcMoveToPreviousRow, [:pointer, :pointer], :int],
|
376
|
+
[:open_connection, :RfcOpenConnection, [:pointer, :uint, :pointer], :pointer],
|
377
|
+
[:ping, :RfcPing, [:pointer, :pointer], :int],
|
378
|
+
[:register_server, :RfcRegisterServer, [:pointer, :uint, :pointer], :pointer],
|
379
|
+
[:reload_ini_file, :RfcReloadIniFile, [:pointer], :int],
|
380
|
+
# [:remove_function_desc, :RfcRemoveFunctionDesc, [:pointer, :pointer, :pointer], :int],
|
381
|
+
# [:remove_type_desc, :RfcRemoveTypeDesc, [:pointer, :pointer, :pointer], :int],
|
382
|
+
[:reset_server_context, :RfcResetServerContext, [:pointer, :pointer], :int],
|
383
|
+
[:sapuc_to_utf8, :RfcSAPUCToUTF8, [:pointer, :uint, :pointer, :pointer, :pointer, :pointer], :int],
|
384
|
+
[:set_bytes, :RfcSetBytes, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
385
|
+
[:set_chars, :RfcSetChars, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
386
|
+
[:set_date, :RfcSetDate, [:pointer, :pointer, :pointer, :pointer], :int],
|
387
|
+
#[:set_dec_f16, :RfcSetDecF16, [:pointer, :pointer, :pointer, :pointer], :int],
|
388
|
+
[:set_dec_f16, :RfcSetDecF16, [:pointer, :pointer, RFC_DECF16.by_value, :pointer], :int],
|
389
|
+
[:set_dec_f34, :RfcSetDecF34, [:pointer, :pointer, :pointer, :pointer], :int],
|
390
|
+
[:set_float, :RfcSetFloat, [:pointer, :pointer, :double, :pointer], :int],
|
391
|
+
[:set_ini_path, :RfcSetIniPath, [:pointer, :pointer], :int],
|
392
|
+
[:set_int, :RfcSetInt, [:pointer, :pointer, :long, :pointer], :int],
|
393
|
+
[:set_int1, :RfcSetInt1, [:pointer, :pointer, :uint8, :pointer], :int],
|
394
|
+
[:set_int2, :RfcSetInt2, [:pointer, :pointer, :short, :pointer], :int],
|
395
|
+
[:set_num, :RfcSetNum, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
396
|
+
[:set_parameter_active, :RfcSetParameterActive, [:pointer, :pointer, :int, :pointer], :int],
|
397
|
+
[:set_string, :RfcSetString, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
398
|
+
[:set_structure, :RfcSetStructure, [:pointer, :pointer, :pointer, :pointer], :int],
|
399
|
+
[:set_table, :RfcSetTable, [:pointer, :pointer, :pointer, :pointer], :int],
|
400
|
+
[:set_time, :RfcSetTime, [:pointer, :pointer, :pointer, :pointer], :int],
|
401
|
+
#[:set_trace_dir, :RfcSetTraceDir, [:pointer, :pointer], :int],
|
402
|
+
#[:set_trace_encoding, :RfcSetTraceEncoding, [:pointer, :pointer], :int],
|
403
|
+
#[:set_trace_level, :RfcSetTraceLevel, [:pointer, :pointer, :uint, :pointer], :int],
|
404
|
+
[:set_type_length, :RfcSetTypeLength, [:pointer, :uint, :uint, :pointer], :int],
|
405
|
+
[:set_x_string, :RfcSetXString, [:pointer, :pointer, :pointer, :uint, :pointer], :int],
|
406
|
+
[:snc_key_to_name, :RfcSNCKeyToName, [:pointer, :pointer, :uint, :pointer, :uint, :pointer], :int],
|
407
|
+
[:snc_name_to_key, :RfcSNCNameToKey, [:pointer, :pointer, :pointer, :pointer, :pointer], :int],
|
408
|
+
[:start_server, :RfcStartServer, [:int, :pointer, :pointer, :uint, :pointer], :pointer],
|
409
|
+
[:submit_transaction, :RfcSubmitTransaction, [:pointer, :pointer], :int],
|
410
|
+
[:utf8_to_sapuc, :RfcUTF8ToSAPUC, [:pointer, :uint, :pointer, :pointer, :pointer, :pointer], :int]
|
411
|
+
].each{|funcsig|
|
412
|
+
attach_function(funcsig[0], funcsig[1], funcsig[2], funcsig[3], :blocking => true)
|
413
|
+
}
|
414
|
+
|
415
|
+
# Take Hash of connection parameters and returns FFI pointer to an array
|
416
|
+
# for passing to connection
|
417
|
+
# ---
|
418
|
+
# TODO - Ideally, this method should live in nwrfc.rb
|
419
|
+
def NWRFCLib.make_conn_params(params) #https://github.com/ffi/ffi/wiki/Structs
|
420
|
+
par = FFI::MemoryPointer.new(RFCConnParam, params.length)
|
421
|
+
pars = params.length.times.collect do |i|
|
422
|
+
RFCConnParam.new(par + i * RFCConnParam.size)
|
423
|
+
end
|
424
|
+
#TODO Optimize this method
|
425
|
+
tpar = params.to_a
|
426
|
+
params.length.times do |n|
|
427
|
+
# str = (tpar[n][0].to_s + "\0").encode("UTF-16LE")
|
428
|
+
pars[n][:name] = FFI::MemoryPointer.from_string(tpar[n][0].to_s.cU)
|
429
|
+
# str = (tpar[n][1].to_s + "\0").encode("UTF-16LE")
|
430
|
+
# str = str.encode("UTF-16LE")
|
431
|
+
pars[n][:value] = FFI::MemoryPointer.from_string(tpar[n][1].to_s.cU)
|
432
|
+
end
|
433
|
+
par
|
434
|
+
end
|
435
|
+
|
436
|
+
end
|