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 <<-CODE_END
      #{type} #{get_constant_method}(void) {
        return #{name};
      }
      CODE_END
    
    @eval_on_load << <<-CODE_END
      #{@mod.name}.const_set(:#{name}, #{get_constant_method})
      CODE_END
  end
end


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 = <<-CODE_END
      #{type.c_transfer_type} #{delegate_function_name}(#{TRANSFER_TYPE} pointer) {
        #{type.c_transfer_type} result = (#{type.c_transfer_type}) ((#{struct_name}*) pointer)->#{field_name};
        #{type.is_simple_type? ? 'return result;' : "if(result) { return result; } else { return(Qfalse); }"}
      }
      CODE_END
    #        puts c_code
    self.c_singleton c_code
    
    #build ruby delegate
    line = __LINE__; ruby_code = <<-CODE_END
      def #{field_name}
        result = (#{@mod.name}.#{delegate_function_name}(memory_address))
        #{type.is_pointer_type? ? 'return nil if !result' : ''}
        #{type.ruby_type_conversion}(result)
      end
      CODE_END
    #        puts ruby_code
    link_type("#{struct_name}*").class_eval ruby_code, __FILE__, line + 1
  end
end


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 = <<-CODE_END
    #{return_type.c_transfer_type} #{delegate_function_name}(#{parameters.c_method_parameters.join(', ')}) {
      #{return_type.void? ? '' : "return (#{return_type.c_transfer_type})"} #{function_name}(#{parameters.c_casted_call_args.join(', ')});
    }
    CODE_END
  #      puts c_code
  self.c_singleton c_code
  
  #build ruby delegate
  line = __LINE__; ruby_code = <<-CODE_END
    def self.#{function_name}(#{parameters.ruby_method_parameters.join(', ')})
      #{parameters.ruby_ref_assigns.reject_nils.join('; ')}
      return_values = []
      #{return_type.void? ? '' : ('return_values << ' + return_type.ruby_type_conversion)}(#{delegate_function_name}(#{parameters.ruby_transformed_call_args.join(', ')}))
      #{parameters.ruby_converted_return_values.reject_nils.prefix('return_values << ').join('; ')}
      case return_values.size
        when 0: nil
        when 1: return_values[0]
        else    return_values
      end
    end
    def #{function_name}(#{parameters.ruby_method_parameters.join(', ')})
      self.class.#{function_name}(#{parameters.arg_names.join(', ')})
    end
    CODE_END
  #      puts ruby_code
  @mod.class_eval ruby_code, __FILE__, line + 1
end


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

#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