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