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.
@@ -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
- @group = NWRFCLib::RFC_ERROR_GROUP[error[:group]]
14
- @message = error[:message].get_str
15
- @type = error[:abapMsgType].get_str
16
- @number = error[:abapMsgNumber].get_str
17
- end
18
-
19
- def inspect
20
- "#{@message} (code #{@code}, group #{@group}, type #{@type}, number #{@number})"
21
- end
22
-
23
- end
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
@@ -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