RubyInline 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +17 -1
- data/Makefile +8 -3
- data/README.txt +10 -9
- data/example.rb +6 -1
- data/inline.gemspec +1 -0
- data/inline.rb +76 -25
- data/test_inline.rb +120 -19
- metadata +6 -6
data/History.txt
CHANGED
@@ -1,7 +1,23 @@
|
|
1
|
+
*** 3.2.0 / 2004-11-27
|
2
|
+
|
3
|
+
+ 8 minor enhancements
|
4
|
+
+ Gemified
|
5
|
+
+ Added #line preprocessor directives to make debugging inside your ruby file practical.
|
6
|
+
+ Added uninstall rule to Makefile
|
7
|
+
+ Inline::C now generates classes directly instead of included modules.
|
8
|
+
+ Better execeptions are thrown on error.
|
9
|
+
+ Incorporated a bunch of changes from Jonathan Paisley:
|
10
|
+
+ Generation of inline'd class methods. (c_singleton and c_raw_singleton)
|
11
|
+
+ Fixed problems with nested module/classes.
|
12
|
+
+ Inline can now extend the same class multiple times.
|
13
|
+
+ 2 bug fixes
|
14
|
+
+ Smarter require/instantiation to accomodate other languages better.
|
15
|
+
+ Fixed a logic error where running good code, then bad, then bad again ran the original good code.
|
16
|
+
|
1
17
|
*** 3.1.0 / 2004-09-24
|
2
18
|
|
3
19
|
+ 2 minor enhancement
|
4
|
-
Extended API of Inline::C with prefix(code).
|
20
|
+
+ Extended API of Inline::C with prefix(code).
|
5
21
|
+ Documented all public API.
|
6
22
|
+ 2 bug fixes
|
7
23
|
+ Cleaned a lot of code and tests.
|
data/Makefile
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
RUBY?=/usr/local/bin/ruby
|
2
2
|
RDOC?=rdoc18
|
3
|
+
RUBYLIB=$(shell $(RUBY) -rrbconfig -e 'include Config; print CONFIG["sitelibdir"]')
|
3
4
|
|
4
5
|
test:
|
5
6
|
$(RUBY) -I. -w ./test_inline.rb
|
@@ -28,10 +29,14 @@ bench:
|
|
28
29
|
@$(RUBY) -I. ./example.rb 2 2> /dev/null
|
29
30
|
|
30
31
|
install:
|
31
|
-
|
32
|
-
|
33
|
-
cp -f inline.rb $$where; \
|
32
|
+
echo "installing inline.rb in $(RUBYLIB)"; \
|
33
|
+
cp -f inline.rb $(RUBYLIB);
|
34
34
|
echo Installed
|
35
35
|
|
36
|
+
uninstall:
|
37
|
+
echo "Removing inline.rb from $(RUBYLIB)"; \
|
38
|
+
rm $(RUBYLIB)/inline.rb;
|
39
|
+
echo Removed
|
40
|
+
|
36
41
|
clean:
|
37
42
|
rm -rf *~ doc ~/.ruby_inline
|
data/README.txt
CHANGED
@@ -5,22 +5,22 @@
|
|
5
5
|
|
6
6
|
** DESCRIPTION:
|
7
7
|
|
8
|
-
Ruby Inline is
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
Ruby Inline is an analog to Perl's Inline::C. Out of the box, it
|
9
|
+
allows you to embed C/++ external module code in your ruby script
|
10
|
+
directly. By writing simple builder classes, you can teach how to cope
|
11
|
+
with new languages (fortran, perl, whatever). The code is compiled and
|
12
|
+
run on the fly when needed.
|
13
13
|
|
14
14
|
** FEATURES/PROBLEMS:
|
15
15
|
|
16
16
|
+ Quick and easy inlining of your C or C++ code embedded in your ruby script.
|
17
|
-
+
|
18
|
-
|
17
|
+
+ Extendable to work with other languages.
|
18
|
+
+ Automatic conversion between ruby and C basic types
|
19
|
+
+ char, unsigned, unsigned int, char *, int, long, unsigned long
|
19
20
|
+ inline_c_raw exists for when the automatic conversion isn't sufficient.
|
20
21
|
+ Only recompiles if the inlined code has changed.
|
21
22
|
+ Pretends to be secure.
|
22
23
|
+ Only uses standard ruby libraries, nothing extra to download.
|
23
|
-
+ Simple as it can be. Less than 230 lines long... um... sorta simple.
|
24
24
|
|
25
25
|
** SYNOPSYS:
|
26
26
|
|
@@ -82,10 +82,11 @@ version, but it is neat!
|
|
82
82
|
|
83
83
|
** REQUIREMENTS:
|
84
84
|
|
85
|
-
+ Ruby - 1.6.7 & 1.
|
85
|
+
+ Ruby - 1.6.7 & 1.8.2 has been used on FreeBSD 4.6+ and MacOSX.
|
86
86
|
+ POSIX compliant system (ie pretty much any UNIX, or Cygwin on MS platforms).
|
87
87
|
+ A C/C++ compiler (the same one that compiled your ruby interpreter).
|
88
88
|
+ test::unit for running tests ( http://testunit.talbott.ws/ ).
|
89
|
+
+ rubygems if you'd like.
|
89
90
|
|
90
91
|
** INSTALL:
|
91
92
|
|
data/example.rb
CHANGED
data/inline.gemspec
CHANGED
@@ -11,6 +11,7 @@ spec = Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
paragraphs = File.read("README.txt").split(/\n\n+/)
|
13
13
|
s.description = paragraphs[3]
|
14
|
+
puts s.description
|
14
15
|
|
15
16
|
s.requirements << "A POSIX environment and a compiler for your language."
|
16
17
|
s.files = IO.readlines("Manifest.txt").map {|f| f.chomp }
|
data/inline.rb
CHANGED
@@ -32,16 +32,19 @@
|
|
32
32
|
|
33
33
|
require "rbconfig"
|
34
34
|
require "ftools"
|
35
|
+
require "digest/md5"
|
35
36
|
|
36
37
|
$TESTING = false unless defined? $TESTING
|
37
38
|
|
39
|
+
class CompilationError < RuntimeError; end
|
40
|
+
|
38
41
|
# The Inline module is the top-level module used. It is responsible
|
39
42
|
# for instantiating the builder for the right language used,
|
40
43
|
# compilation/linking when needed, and loading the inlined code into
|
41
44
|
# the current namespace.
|
42
45
|
|
43
46
|
module Inline
|
44
|
-
VERSION = '3.
|
47
|
+
VERSION = '3.2.0'
|
45
48
|
|
46
49
|
$stderr.puts "RubyInline v #{VERSION}" if $DEBUG
|
47
50
|
|
@@ -96,12 +99,12 @@ module Inline
|
|
96
99
|
}
|
97
100
|
|
98
101
|
def ruby2c(type)
|
99
|
-
raise "Unknown type #{type}" unless @@type_map.has_key? type
|
102
|
+
raise ArgumentError, "Unknown type #{type}" unless @@type_map.has_key? type
|
100
103
|
@@type_map[type].first
|
101
104
|
end
|
102
105
|
|
103
106
|
def c2ruby(type)
|
104
|
-
raise "Unknown type #{type}" unless @@type_map.has_key? type
|
107
|
+
raise ArgumentError, "Unknown type #{type}" unless @@type_map.has_key? type
|
105
108
|
@@type_map[type].last
|
106
109
|
end
|
107
110
|
|
@@ -152,11 +155,17 @@ module Inline
|
|
152
155
|
}
|
153
156
|
end
|
154
157
|
|
155
|
-
raise "
|
158
|
+
raise SyntaxError, "Can't parse signature: #{sig}"
|
156
159
|
end # def parse_signature
|
157
160
|
|
158
|
-
def generate(src,
|
161
|
+
def generate(src, options={})
|
162
|
+
|
163
|
+
if not Hash === options then
|
164
|
+
options = {:expand_types=>options}
|
165
|
+
end
|
159
166
|
|
167
|
+
expand_types = options[:expand_types]
|
168
|
+
singleton = options[:singleton]
|
160
169
|
result = self.strip_comments(src)
|
161
170
|
|
162
171
|
signature = parse_signature(src, !expand_types)
|
@@ -190,7 +199,7 @@ module Inline
|
|
190
199
|
result.sub!(/[^;\/\"\>]+#{function_name}\s*\([^\{]+\{/, "\n" + prefix)
|
191
200
|
result.sub!(/\A\n/, '') # strip off the \n in front in case we added it
|
192
201
|
unless return_type == "void" then
|
193
|
-
raise "
|
202
|
+
raise SyntaxError, "Couldn't find return statement for #{function_name}" unless
|
194
203
|
result =~ /return/
|
195
204
|
result.gsub!(/return\s+([^\;\}]+)/) do
|
196
205
|
"return #{c2ruby(return_type)}(#{$1})"
|
@@ -204,8 +213,11 @@ module Inline
|
|
204
213
|
result.sub!(/\A\n/, '') # strip off the \n in front in case we added it
|
205
214
|
end
|
206
215
|
|
216
|
+
file, line = caller[1].split(/:/)
|
217
|
+
result = "# line #{line.to_i - 1} \"#{file}\"\n" + result
|
218
|
+
|
207
219
|
@src << result
|
208
|
-
@sig[function_name] = arity
|
220
|
+
@sig[function_name] = [arity,singleton]
|
209
221
|
|
210
222
|
return result if $TESTING
|
211
223
|
end # def generate
|
@@ -215,14 +227,14 @@ module Inline
|
|
215
227
|
public
|
216
228
|
|
217
229
|
def load
|
218
|
-
require "#{@so_name}" or raise "require on #{@so_name} failed"
|
219
|
-
@mod.class_eval "include #{@mod_name}"
|
230
|
+
require "#{@so_name}" or raise LoadError, "require on #{@so_name} failed"
|
220
231
|
end
|
221
232
|
|
222
233
|
def build
|
223
234
|
rb_file = File.expand_path(caller[1].split(/:/).first) # [MS]
|
235
|
+
so_exists = File.file? @so_name
|
224
236
|
|
225
|
-
unless
|
237
|
+
unless so_exists and File.mtime(@rb_file) < File.mtime(@so_name)
|
226
238
|
|
227
239
|
src_name = "#{Inline.directory}/#{@mod_name}.c"
|
228
240
|
old_src_name = "#{src_name}.old"
|
@@ -233,15 +245,21 @@ module Inline
|
|
233
245
|
io.puts @src.join("\n\n")
|
234
246
|
io.puts
|
235
247
|
io.puts
|
236
|
-
io.puts " VALUE c#{@mod_name};"
|
237
248
|
io.puts "#ifdef __cplusplus"
|
238
249
|
io.puts "extern \"C\" {"
|
239
250
|
io.puts "#endif"
|
240
251
|
io.puts " void Init_#{@mod_name}() {"
|
241
|
-
|
252
|
+
io.puts " VALUE c = rb_cObject;"
|
253
|
+
@mod.name.split("::").each do |n|
|
254
|
+
io.puts " c = rb_const_get_at(c,rb_intern(\"#{n}\"));"
|
255
|
+
end
|
242
256
|
@sig.keys.sort.each do |name|
|
243
|
-
arity = @sig[name]
|
244
|
-
|
257
|
+
arity, singleton = @sig[name]
|
258
|
+
if singleton then
|
259
|
+
io.print " rb_define_singleton_method(c, \"#{name}\", "
|
260
|
+
else
|
261
|
+
io.print " rb_define_method(c, \"#{name}\", "
|
262
|
+
end
|
245
263
|
io.puts "(VALUE(*)(ANYARGS))#{name}, #{arity});"
|
246
264
|
end
|
247
265
|
io.puts
|
@@ -254,13 +272,15 @@ module Inline
|
|
254
272
|
|
255
273
|
# recompile only if the files are different
|
256
274
|
recompile = true
|
257
|
-
if
|
275
|
+
if so_exists and should_compare and
|
276
|
+
File::compare(old_src_name, src_name, $DEBUG) then
|
258
277
|
recompile = false
|
259
278
|
|
260
279
|
# Updates the timestamps on all the generated/compiled files.
|
261
280
|
# Prevents us from entering this conditional unless the source
|
262
281
|
# file changes again.
|
263
|
-
|
282
|
+
t = Time.now
|
283
|
+
File.utime(t, t, src_name, old_src_name, @so_name)
|
264
284
|
end
|
265
285
|
|
266
286
|
if recompile then
|
@@ -287,10 +307,16 @@ module Inline
|
|
287
307
|
if /mswin32/ =~ RUBY_PLATFORM then
|
288
308
|
cmd += " -link /INCREMENTAL:no /EXPORT:Init_#{@mod_name}"
|
289
309
|
end
|
310
|
+
|
311
|
+
cmd += " 2> /dev/null" if $TESTING
|
290
312
|
|
291
313
|
$stderr.puts "Building #{@so_name} with '#{cmd}'" if $DEBUG
|
292
314
|
`#{cmd}`
|
293
|
-
|
315
|
+
if $? != 0 then
|
316
|
+
bad_src_name = src_name + ".bad"
|
317
|
+
File.rename src_name, bad_src_name
|
318
|
+
raise CompilationError, "error executing #{cmd}: #{$?}\nRenamed #{src_name} to #{bad_src_name}"
|
319
|
+
end
|
294
320
|
$stderr.puts "Built successfully" if $DEBUG
|
295
321
|
end
|
296
322
|
|
@@ -299,10 +325,20 @@ module Inline
|
|
299
325
|
end # unless (file is out of date)
|
300
326
|
end # def build
|
301
327
|
|
328
|
+
attr_reader :mod
|
302
329
|
def initialize(mod)
|
303
330
|
@mod = mod
|
304
|
-
|
305
|
-
|
331
|
+
if @mod then
|
332
|
+
# Figure out which script file defined the C code
|
333
|
+
@rb_file = File.expand_path(caller[2].split(/:/).first) # [MS]
|
334
|
+
# Extract the basename of the script and clean it up to be
|
335
|
+
# a valid C identifier
|
336
|
+
rb_script_name = File.basename(@rb_file).gsub(/[^a-zA-Z0-9_]/,'_')
|
337
|
+
# Hash the full path to the script
|
338
|
+
suffix = Digest::MD5.new(@rb_file).to_s[0,4]
|
339
|
+
@mod_name = "Inline_#{@mod.name.gsub('::','__')}_#{rb_script_name}_#{suffix}"
|
340
|
+
@so_name = "#{Inline.directory}/#{@mod_name}.#{Config::CONFIG["DLEXT"]}"
|
341
|
+
end
|
306
342
|
@src = []
|
307
343
|
@sig = {}
|
308
344
|
@flags = []
|
@@ -350,7 +386,11 @@ module Inline
|
|
350
386
|
# conversions can be extended by using +add_type_converter+.
|
351
387
|
|
352
388
|
def c src
|
353
|
-
self.generate(src)
|
389
|
+
self.generate(src,:expand_types=>true)
|
390
|
+
end
|
391
|
+
|
392
|
+
def c_singleton src
|
393
|
+
self.generate(src,:expand_types=>true,:singleton=>true)
|
354
394
|
end
|
355
395
|
|
356
396
|
# Adds a raw C function to the source. This version does not
|
@@ -358,7 +398,11 @@ module Inline
|
|
358
398
|
# coding conventions.
|
359
399
|
|
360
400
|
def c_raw src
|
361
|
-
self.generate(src
|
401
|
+
self.generate(src)
|
402
|
+
end
|
403
|
+
|
404
|
+
def c_raw_singleton src
|
405
|
+
self.generate(src, :singleton=>true)
|
362
406
|
end
|
363
407
|
|
364
408
|
end # class Inline::C
|
@@ -371,8 +415,15 @@ class Module
|
|
371
415
|
# parameter.
|
372
416
|
|
373
417
|
def inline(lang = :C, testing=false)
|
374
|
-
|
375
|
-
|
418
|
+
|
419
|
+
begin
|
420
|
+
builder_class = Inline.const_get(lang)
|
421
|
+
rescue NameError
|
422
|
+
require "inline/#{lang}"
|
423
|
+
builder_class = Inline.const_get(lang)
|
424
|
+
end
|
425
|
+
|
426
|
+
builder = builder_class.new self
|
376
427
|
|
377
428
|
yield builder
|
378
429
|
|
@@ -417,9 +468,9 @@ class Dir
|
|
417
468
|
mode = File.stat(path).mode
|
418
469
|
unless ((mode % 01000) & 0022) == 0 then
|
419
470
|
if $TESTING then
|
420
|
-
raise
|
471
|
+
raise SecurityError, "Directory #{path} is insecure"
|
421
472
|
else
|
422
|
-
$stderr.puts "#{path} is insecure (#{sprintf('%o', mode)}), needs 0700 for perms"
|
473
|
+
$stderr.puts "#{path} is insecure (#{sprintf('%o', mode)}), needs 0700 for perms. Exiting."
|
423
474
|
exit 1
|
424
475
|
end
|
425
476
|
end
|
data/test_inline.rb
CHANGED
@@ -1,16 +1,13 @@
|
|
1
|
-
#!/usr/bin/ruby -w
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
2
|
|
3
3
|
$TESTING = true
|
4
4
|
|
5
5
|
require 'inline'
|
6
|
+
require 'tempfile'
|
6
7
|
require 'test/unit'
|
7
8
|
|
8
9
|
File.umask(0)
|
9
10
|
|
10
|
-
#class TestFile < Test::Unit::TestCase
|
11
|
-
# TODO def test_write_with_backup
|
12
|
-
#end
|
13
|
-
|
14
11
|
class TestDir < Test::Unit::TestCase
|
15
12
|
|
16
13
|
def setup
|
@@ -32,7 +29,7 @@ class TestDir < Test::Unit::TestCase
|
|
32
29
|
Dir.assert_secure path
|
33
30
|
end
|
34
31
|
else
|
35
|
-
assert_raises(perms.nil? ? Errno::ENOENT :
|
32
|
+
assert_raises(perms.nil? ? Errno::ENOENT : SecurityError) do
|
36
33
|
Dir.assert_secure path
|
37
34
|
end
|
38
35
|
end
|
@@ -103,7 +100,7 @@ class TestC < Test::Unit::TestCase
|
|
103
100
|
assert_equal 'NUM2UINT', x.ruby2c("unsigned long")
|
104
101
|
assert_equal 'NUM2UINT', x.ruby2c("unsigned")
|
105
102
|
|
106
|
-
assert_raises
|
103
|
+
assert_raises ArgumentError do
|
107
104
|
x.ruby2c('blah')
|
108
105
|
end
|
109
106
|
end
|
@@ -118,7 +115,7 @@ class TestC < Test::Unit::TestCase
|
|
118
115
|
assert_equal 'UINT2NUM', x.c2ruby("unsigned long")
|
119
116
|
assert_equal 'UINT2NUM', x.c2ruby("unsigned")
|
120
117
|
|
121
|
-
assert_raises
|
118
|
+
assert_raises ArgumentError do
|
122
119
|
x.c2ruby('blah')
|
123
120
|
end
|
124
121
|
end
|
@@ -216,6 +213,8 @@ class TestC < Test::Unit::TestCase
|
|
216
213
|
inline do |builder|
|
217
214
|
result = builder.generate src, expand_types
|
218
215
|
end
|
216
|
+
result.gsub!(/\# line \d+/, '# line N')
|
217
|
+
expected = '# line N "./test_inline.rb"' + "\n" + expected
|
219
218
|
assert_equal(expected, result)
|
220
219
|
end
|
221
220
|
|
@@ -425,7 +424,9 @@ puts(s); return rb_str_new2(s)}"
|
|
425
424
|
result = builder.c "int add(int a, int b) { return a + b; }"
|
426
425
|
end
|
427
426
|
|
428
|
-
expected = "
|
427
|
+
expected = "# line N \"./test_inline.rb\"\nstatic VALUE add(VALUE self, VALUE _a, VALUE _b) {\n int a = FIX2INT(_a);\n int b = FIX2INT(_b);\n return INT2FIX(a + b); }"
|
428
|
+
|
429
|
+
result.gsub!(/\# line \d+/, '# line N')
|
429
430
|
|
430
431
|
assert_equal expected, result
|
431
432
|
assert_equal [expected], builder.src
|
@@ -439,19 +440,103 @@ puts(s); return rb_str_new2(s)}"
|
|
439
440
|
result = builder.c_raw src.dup
|
440
441
|
end
|
441
442
|
|
442
|
-
|
443
|
+
result.gsub!(/\# line \d+/, '# line N')
|
444
|
+
expected = "# line N \"./test_inline.rb\"\n" + src
|
443
445
|
|
444
446
|
assert_equal expected, result
|
445
447
|
assert_equal [expected], builder.src
|
446
448
|
end
|
447
449
|
|
448
|
-
|
449
|
-
|
450
|
-
|
450
|
+
def util_simple_code(klassname, c_src)
|
451
|
+
result = "
|
452
|
+
require 'inline'
|
453
|
+
|
454
|
+
class #{klassname}
|
455
|
+
inline do |builder|
|
456
|
+
builder.c <<-EOC
|
457
|
+
#{c_src}
|
458
|
+
EOC
|
459
|
+
end
|
460
|
+
end"
|
461
|
+
result
|
462
|
+
end
|
463
|
+
|
464
|
+
def util_test_build(src)
|
465
|
+
tempfile = Tempfile.new("util_test_build")
|
466
|
+
tempfile.write src
|
467
|
+
tempfile.flush
|
468
|
+
tempfile.rewind
|
469
|
+
rb_file = tempfile.path + ".rb"
|
470
|
+
File.rename tempfile.path, rb_file
|
471
|
+
begin
|
472
|
+
Kernel.module_eval { require rb_file }
|
473
|
+
yield if block_given?
|
474
|
+
rescue Exception => err
|
475
|
+
raise err
|
476
|
+
ensure
|
477
|
+
File.unlink rb_file
|
478
|
+
end
|
479
|
+
end
|
480
|
+
|
481
|
+
def test_build_good
|
482
|
+
code = util_simple_code(:DumbTest1, "long dumbpi() { return 314; }")
|
483
|
+
util_test_build(code) do
|
484
|
+
result = DumbTest1.new.dumbpi
|
485
|
+
assert_equal(314, result)
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_build_bad
|
490
|
+
code = util_simple_code(:DumbTest2, "void should_puke() { 1+1 2+2 }")
|
491
|
+
assert_raises(CompilationError) do
|
492
|
+
util_test_build(code) do
|
493
|
+
flunk
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
def test_load
|
499
|
+
# totally tested by test_build
|
500
|
+
end
|
451
501
|
|
452
502
|
end # class TestC
|
453
503
|
end # class TestInline
|
454
504
|
|
505
|
+
$test_module_code = <<-EOR
|
506
|
+
module Foo
|
507
|
+
class Bar
|
508
|
+
inline do |builder|
|
509
|
+
builder.c <<-EOC
|
510
|
+
static int forty_two_instance() { return 42; }
|
511
|
+
EOC
|
512
|
+
builder.c_singleton <<-EOC
|
513
|
+
static int twenty_four_class() { return 24; }
|
514
|
+
EOC
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
EOR
|
519
|
+
|
520
|
+
$test_module_code2 = <<-EOR
|
521
|
+
require 'inline'
|
522
|
+
|
523
|
+
# Demonstrates native functions in nested classes and
|
524
|
+
# extending a class more than once from different ruby
|
525
|
+
# source files
|
526
|
+
module Foo
|
527
|
+
class Bar
|
528
|
+
inline do |builder|
|
529
|
+
builder.c <<-EOC
|
530
|
+
int twelve_instance() { return 12; }
|
531
|
+
EOC
|
532
|
+
builder.c_singleton <<-EOC
|
533
|
+
int twelve_class() { return 12; }
|
534
|
+
EOC
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
EOR
|
539
|
+
|
455
540
|
class TestModule < Test::Unit::TestCase
|
456
541
|
|
457
542
|
def setup
|
@@ -463,19 +548,35 @@ class TestModule < Test::Unit::TestCase
|
|
463
548
|
`rm -rf #{@rootdir}` unless $DEBUG
|
464
549
|
end
|
465
550
|
|
551
|
+
def test_nested
|
552
|
+
Object.class_eval $test_module_code
|
553
|
+
fb = Foo::Bar.new
|
554
|
+
assert_equal(fb.forty_two_instance, 42)
|
555
|
+
assert_equal(Foo::Bar.twenty_four_class, 24)
|
556
|
+
|
557
|
+
tempfile = Tempfile.new("test_inline_nested")
|
558
|
+
tempfile.write($test_module_code2)
|
559
|
+
tempfile.flush
|
560
|
+
tempfile.rewind
|
561
|
+
`cp #{tempfile.path} #{tempfile.path}.rb`
|
562
|
+
require "#{tempfile.path}.rb"
|
563
|
+
assert_equal(fb.twelve_instance,12)
|
564
|
+
assert_equal(Foo::Bar.twelve_class,12)
|
565
|
+
`rm "#{tempfile.path}.rb"`
|
566
|
+
end
|
567
|
+
|
466
568
|
def test_inline
|
467
569
|
self.class.inline(:C) do |builder|
|
468
570
|
builder.c "int add(int a, int b) { return a + b; }"
|
469
571
|
end
|
470
572
|
assert(test(?d, Inline.directory),
|
471
573
|
"inline dir should have been created")
|
472
|
-
|
473
|
-
|
474
|
-
assert(test(?f, File.join(Inline.directory,
|
475
|
-
"Mod_TestModule.#{Config::CONFIG["DLEXT"]}")),
|
574
|
+
matches = Dir[File.join(Inline.directory, "Inline_TestModule_test_inline_rb_*.c")]
|
575
|
+
assert_equal(matches.length,1,
|
476
576
|
"Source should have been created")
|
577
|
+
library_file = matches.first.gsub(/\.c$/) { "." + Config::CONFIG["DLEXT"] }
|
578
|
+
assert(test(?f, library_file),
|
579
|
+
"Library file should have been created")
|
477
580
|
end
|
478
581
|
|
479
582
|
end
|
480
|
-
|
481
|
-
# Number of errors detected: 4
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: RubyInline
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 3.
|
7
|
-
date: 2004-11-
|
6
|
+
version: 3.2.0
|
7
|
+
date: 2004-11-27
|
8
8
|
summary: Multi-language extension coding within ruby.
|
9
9
|
require_paths:
|
10
10
|
- "."
|
@@ -12,10 +12,10 @@ author: Ryan Davis
|
|
12
12
|
email: ryand-ruby@zenspider.com
|
13
13
|
homepage: http://www.zenspider.com/ZSS/Products/RubyInline/
|
14
14
|
rubyforge_project: rubyinline
|
15
|
-
description: "Ruby Inline is
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
description: "Ruby Inline is an analog to Perl's Inline::C. Out of the box, it allows you to
|
16
|
+
embed C/++ external module code in your ruby script directly. By writing simple
|
17
|
+
builder classes, you can teach how to cope with new languages (fortran, perl,
|
18
|
+
whatever). The code is compiled and run on the fly when needed."
|
19
19
|
autorequire: inline
|
20
20
|
default_executable:
|
21
21
|
bindir: bin
|