RubyInline 3.1.0 → 3.2.0
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.
- 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
|