nwrfc 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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