Class: Inline::C

Inherits:
Object
  • Object
show all
Defined in:
lib/inline_acceleration.rb

Defined Under Namespace

Modules: Pointer Classes: Parameter, Type, Value

Constant Summary collapse

TRANSFER_TYPE =

TRANSFER_TYPE = $TESTING ? ‘unsigned long’ : ‘VALUE’

'long'
@@internal_c_functions =
[]
@@internal_c_functions_module =
nil

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mod) ⇒ C

Returns a new instance of C.



134
135
136
137
138
139
140
141
# File 'lib/inline_acceleration.rb', line 134

def initialize(mod)
  initialize_orig(mod)
  if @@internal_c_functions_module.nil?
    @@internal_c_functions.each { |function| self.c_singleton(function) }
    @@internal_c_functions_module = mod
  end
  @eval_on_load = ''
end

Class Method Details

.internal_c_functionsObject



121
122
123
# File 'lib/inline_acceleration.rb', line 121

def self.internal_c_functions
  @@internal_c_functions
end

.internal_c_functions_moduleObject



125
126
127
# File 'lib/inline_acceleration.rb', line 125

def self.internal_c_functions_module
  @@internal_c_functions_module
end

.type_mapObject



129
130
131
# File 'lib/inline_acceleration.rb', line 129

def self.type_map
  @@type_map
end

Instance Method Details

#initialize_origObject



133
# File 'lib/inline_acceleration.rb', line 133

alias_method :initialize_orig, :initialize


310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/inline_acceleration.rb', line 310

def link_constants(type, names)
  names.each do |name|
    get_constant_method = "get_constant_#{name}"
    
    self.c_singleton "      \#{type} \#{get_constant_method}(void) {\n        return \#{name};\n      }\n      CODE_END\n    \n    @eval_on_load << <<-CODE_END\n      \#{@mod.name}.const_set(:\#{name}, \#{get_constant_method})\n      CODE_END\n  end\nend\n"


184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/inline_acceleration.rb', line 184

def link_fields(struct_name, field_hash)
  field_hash.each do |field_name, c_type|
    delegate_function_name = "#{struct_name.gsub(' ', '_')}_#{field_name}"
    type = Type.new(c_type, link_type(c_type))
    
    #build c delegate
    c_code = "      \#{type.c_transfer_type} \#{delegate_function_name}(\#{TRANSFER_TYPE} pointer) {\n        \#{type.c_transfer_type} result = (\#{type.c_transfer_type}) ((\#{struct_name}*) pointer)->\#{field_name};\n        \#{type.is_simple_type? ? 'return result;' : \"if(result) { return result; } else { return(Qfalse); }\"}\n      }\n      CODE_END\n    #        puts c_code\n    self.c_singleton c_code\n    \n    #build ruby delegate\n    line = __LINE__; ruby_code = <<-CODE_END\n      def \#{field_name}\n        result = (\#{@mod.name}.\#{delegate_function_name}(memory_address))\n        \#{type.is_pointer_type? ? 'return nil if !result' : ''}\n        \#{type.ruby_type_conversion}(result)\n      end\n      CODE_END\n    #        puts ruby_code\n    link_type(\"\#{struct_name}*\").class_eval ruby_code, __FILE__, line + 1\n  end\nend\n"


149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/inline_acceleration.rb', line 149

def link_function(c_return_type, function_name, parameter_types)
  delegate_function_name = "C_delegate_#{function_name}"
  return_type = Type.new(c_return_type, link_type(c_return_type))
  parameters = parameter_types.map_with_indices { |type, index| Parameter.new(type, link_type(type), index)  }
  
  #build c delegate
  c_code = "    \#{return_type.c_transfer_type} \#{delegate_function_name}(\#{parameters.c_method_parameters.join(', ')}) {\n      \#{return_type.void? ? '' : \"return (\#{return_type.c_transfer_type})\"} \#{function_name}(\#{parameters.c_casted_call_args.join(', ')});\n    }\n    CODE_END\n  #      puts c_code\n  self.c_singleton c_code\n  \n  #build ruby delegate\n  line = __LINE__; ruby_code = <<-CODE_END\n    def self.\#{function_name}(\#{parameters.ruby_method_parameters.join(', ')})\n      \#{parameters.ruby_ref_assigns.reject_nils.join('; ')}\n      return_values = []\n      \#{return_type.void? ? '' : ('return_values << ' + return_type.ruby_type_conversion)}(\#{delegate_function_name}(\#{parameters.ruby_transformed_call_args.join(', ')}))\n      \#{parameters.ruby_converted_return_values.reject_nils.prefix('return_values << ').join('; ')}\n      case return_values.size\n        when 0: nil\n        when 1: return_values[0]\n        else    return_values\n      end\n    end\n    def \#{function_name}(\#{parameters.ruby_method_parameters.join(', ')})\n      self.class.\#{function_name}(\#{parameters.arg_names.join(', ')})\n    end\n    CODE_END\n  #      puts ruby_code\n  @mod.class_eval ruby_code, __FILE__, line + 1\nend\n"


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/inline_acceleration.rb', line 212

def link_type(c_type, reallocate_pointers=false, &block)
  is_simple_type = @@type_map.has_key?(c_type)
  is_pointer = c_type[-1..-1] == '*'
  return nil if is_simple_type
  return Value if !is_pointer
  
  c_inner_type = c_type[0..-2].strip
  class_name = c_inner_type.gsub(' ', '_').capitalize
  klass = "#{@mod.name}::#{class_name}".to_class
  if !klass
    inner_type = Type.new(c_inner_type, nil)
    is_simple_type = @@type_map.has_key?(c_inner_type)
    
    klass = Class.new()
    @mod.const_set(class_name.to_sym, klass)

    line = __LINE__; ruby_code = "      include Inline::C::Pointer\n     \n      def dereference\n        \#{link_type('void *').name}.new(Inline::C.internal_c_functions_module.C_Pointer_dereference_to_pointer(memory_address))\n      end\n      \n      alias_method :throw_method_missing, :method_missing\n      def method_missing(name, *args, &block)\n        if name.to_s[0..2] == 'to_'\n          type = name.to_s[3..-1]\n          klass = (\"\#{@mod.name}::\" + type.capitalize).to_class\n          return klass.new(memory_address, ruby_managed)\n        end\n        throw_method_missing(name, *args, &block)\n      end\n      CODE_END\n    klass.class_eval ruby_code, __FILE__, line + 1\n    \n    if !inner_type.void?\n      create_pointer_from_data_function_name = \"\#{class_name}_create_pointer_from_data\"\n      create_pointer_from_pointer_function_name = \"\#{class_name}_create_pointer_from_pointer\"\n      get_array_entry_function_name = \"\#{class_name}_get_array_entry\"\n    \n      #create pointer from data\n      c_code = <<-CODE_END\n        \#{TRANSFER_TYPE} \#{create_pointer_from_data_function_name}(\#{is_simple_type ? c_inner_type : TRANSFER_TYPE} source) {\n          \#{c_type} pointer = (\#{c_type}) malloc(sizeof(\#{c_inner_type}));\n          memcpy(pointer, &source, sizeof(\#{c_inner_type}));\n          return (\#{TRANSFER_TYPE}) pointer;\n        }\n        CODE_END\n      self.c_singleton c_code\n      \n      #create pointer from pointer\n      c_code = <<-CODE_END\n        \#{TRANSFER_TYPE} \#{create_pointer_from_pointer_function_name}(\#{TRANSFER_TYPE} source) {\n          \#{c_type} pointer = (\#{c_type}) malloc(sizeof(\#{c_inner_type}));\n          *pointer = *((\#{c_type}) source);\n          return (\#{TRANSFER_TYPE}) pointer;\n        }\n        CODE_END\n      self.c_singleton c_code\n      \n      #array delegate\n      c_code = <<-CODE_END\n        \#{TRANSFER_TYPE} \#{get_array_entry_function_name}(\#{TRANSFER_TYPE} source, long index) {\n          return (\#{TRANSFER_TYPE}) &((\#{c_type}) source)[index];\n        }\n        CODE_END\n      self.c_singleton c_code\n      \n      line = __LINE__; ruby_code = <<-CODE_END\n        @@reallocate_pointers = \#{reallocate_pointers}\n        def self.reallocate_pointers?\n          @@reallocate_pointers\n        end\n        \n        def self.create(source=0)\n          if source.is_a? Inline::C::Pointer\n            if !@@reallocate_pointers\n              source\n            else\n              self.new(\#{@mod.name}.\#{create_pointer_from_pointer_function_name}(source.memory_address), true)\n            end\n          else\n            self.new(\#{@mod.name}.\#{create_pointer_from_data_function_name}(Inline::C::Value.get_data(source)), true)\n          end\n        end\n      \n        def [](index)\n          self.class.new(\#{@mod.name}.\#{get_array_entry_function_name}(self.memory_address, index), self.ruby_managed)\n        end\n      CODE_END\n      klass.class_eval ruby_code, __FILE__, line + 1\n    end\n  end\n  \n  klass.class_eval(&block) if block\n  klass\nend\n"

#loadObject



144
145
146
147
# File 'lib/inline_acceleration.rb', line 144

def load
  load_orig
  @mod.class_eval(@eval_on_load)
end

#load_origObject



143
# File 'lib/inline_acceleration.rb', line 143

alias_method :load_orig, :load