fiddley 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5efaacddbd8392ed670102f7b62b32fe2a6024c
4
+ data.tar.gz: 20a196def56f4a803388c342ad513832fd7632ff
5
+ SHA512:
6
+ metadata.gz: 231465cbe7a2a2a87ca7dc43b0186d8f0df8d044b9ae0ab0ea0ea76c11d99ac9a622444739501bd7536233a6eb77c20be99c51f9e406dd9f61440f812dfbf083
7
+ data.tar.gz: 924b4785615ba80370947d36fa9c7263e38cd763fd63c2198cf23a56a9a6847fb4770f9ba60130a397592a6484e4ae358d8b2f847d61ac6bd791285822e4b9e8
@@ -0,0 +1,38 @@
1
+ Fiddley
2
+ =======
3
+
4
+ Ruby-FFI compatible API layer for Fiddle.
5
+
6
+
7
+ Status
8
+ ------
9
+
10
+ Under development.
11
+
12
+
13
+
14
+ License
15
+ -------
16
+
17
+ Copyright (c) 2017 NAKAMURA Usaku usa@garbagecollect.jp
18
+
19
+ Redistribution and use in source and binary forms, with or without
20
+ modification, are permitted provided that the following conditions are met:
21
+
22
+ 1. Redistributions of source code must retain the above copyright notice,
23
+ this list of conditions and the following disclaimer.
24
+ 2. Redistributions in binary form must reproduce the above copyright notice,
25
+ this list of conditions and the following disclaimer in the documentation
26
+ and/or other materials provided with the distribution.
27
+
28
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
29
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
30
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31
+ DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
32
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
34
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
35
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+
@@ -0,0 +1,10 @@
1
+ # -*- Ruby -*-
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask.rb"
4
+
5
+ task :default => :test
6
+
7
+ desc "Run all tests"
8
+ task :test do
9
+ ruby "-Ilib test/sample.rb"
10
+ end
@@ -0,0 +1,20 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "fiddley"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fiddley"
7
+ spec.version = Fiddley::VERSION
8
+ spec.authors = ["U.Nakamura"]
9
+ spec.email = ["usa@garbagecollect.jp"]
10
+
11
+ spec.summary = "FFI compatible interface for Fiddle"
12
+ spec.description = "Use Fiddle instead of Ruby-FFI !!!"
13
+ spec.homepage = "https://github.com/unak/fiddley"
14
+ spec.license = "BSD-2-Clause"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^tmp/|^tools/|^examples/|^\.}) }
17
+ spec.bindir = "bin"
18
+ spec.executables = []
19
+ spec.require_paths = ["lib"]
20
+ end
@@ -0,0 +1 @@
1
+ require "fiddley"
@@ -0,0 +1,11 @@
1
+ module Fiddley
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+ FFI = Fiddley
6
+
7
+ require "fiddley/function"
8
+ require "fiddley/memory_pointer"
9
+ require "fiddley/library"
10
+ require "fiddley/struct"
11
+ require "fiddley/utils"
@@ -0,0 +1,13 @@
1
+ require "fiddle/import"
2
+
3
+ module Fiddley
4
+ class Function
5
+ def initialize(ret, params, blk)
6
+ Module.new do
7
+ extend Fiddle::Importer
8
+ dlload Fiddley::Library::LIBC
9
+ @@func = bind("#{Fiddley.type2str(ret)} callback(#{params.map{|e|Fiddley.type2str(e)}.join(', ')})", &blk)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,97 @@
1
+ require "fiddle/import"
2
+
3
+ module Fiddley
4
+ module Library
5
+ include Fiddle::Importer
6
+ alias ffi_lib dlload
7
+
8
+ def extended(mod)
9
+ @convention = nil
10
+ end
11
+
12
+ def attach_function(rname, cname, params, ret = nil, blocking: false)
13
+ if ret.nil?
14
+ ret = params
15
+ params = cname
16
+ cname = rname
17
+ end
18
+ extern "#{Fiddley.type2str(ret)} #{cname}(#{params.map{|e| Fiddley.type2str(e)}.join(', ')})", @convention
19
+ if cname != rname
20
+ instance_eval <<-end
21
+ alias #{rname.inspect} #{cname.inspect}
22
+ end
23
+ end
24
+ end
25
+
26
+ def ffi_convention(conv)
27
+ @convention = conv
28
+ end
29
+
30
+ case RUBY_PLATFORM
31
+ when /cygwin/
32
+ libc_so = "cygwin1.dll"
33
+ libm_so = "cygwin1.dll"
34
+ when /linux/
35
+ libdir = '/lib'
36
+ case [0].pack('L!').size
37
+ when 4
38
+ # 32-bit ruby
39
+ libdir = '/lib32' if File.directory? '/lib32'
40
+ when 8
41
+ # 64-bit ruby
42
+ libdir = '/lib64' if File.directory? '/lib64'
43
+ end
44
+ libc_so = File.join(libdir, "libc.so.6")
45
+ libm_so = File.join(libdir, "libm.so.6")
46
+ when /mingw/, /mswin/
47
+ require "rbconfig"
48
+ crtname = RbConfig::CONFIG["RUBY_SO_NAME"][/msvc\w+/] || 'ucrtbase'
49
+ libc_so = libm_so = "#{crtname}.dll"
50
+ when /darwin/
51
+ libc_so = "/usr/lib/libc.dylib"
52
+ libm_so = "/usr/lib/libm.dylib"
53
+ when /kfreebsd/
54
+ libc_so = "/lib/libc.so.0.1"
55
+ libm_so = "/lib/libm.so.1"
56
+ when /gnu/ #GNU/Hurd
57
+ libc_so = "/lib/libc.so.0.3"
58
+ libm_so = "/lib/libm.so.6"
59
+ when /mirbsd/
60
+ libc_so = "/usr/lib/libc.so.41.10"
61
+ libm_so = "/usr/lib/libm.so.7.0"
62
+ when /freebsd/
63
+ libc_so = "/lib/libc.so.7"
64
+ libm_so = "/lib/libm.so.5"
65
+ when /bsd|dragonfly/
66
+ libc_so = "/usr/lib/libc.so"
67
+ libm_so = "/usr/lib/libm.so"
68
+ when /solaris/
69
+ libdir = '/lib'
70
+ case [0].pack('L!').size
71
+ when 4
72
+ # 32-bit ruby
73
+ libdir = '/lib' if File.directory? '/lib'
74
+ when 8
75
+ # 64-bit ruby
76
+ libdir = '/lib/64' if File.directory? '/lib/64'
77
+ end
78
+ libc_so = File.join(libdir, "libc.so")
79
+ libm_so = File.join(libdir, "libm.so")
80
+ end
81
+
82
+ libc_so = nil if !libc_so || (libc_so[0] == ?/ && !File.file?(libc_so))
83
+ libm_so = nil if !libm_so || (libm_so[0] == ?/ && !File.file?(libm_so))
84
+
85
+ if !libc_so || !libm_so
86
+ ruby = EnvUtil.rubybin
87
+ ldd = `ldd #{ruby}`
88
+ #puts ldd
89
+ libc_so = $& if !libc_so && %r{/\S*/libc\.so\S*} =~ ldd
90
+ libm_so = $& if !libm_so && %r{/\S*/libm\.so\S*} =~ ldd
91
+ #p [libc_so, libm_so]
92
+ end
93
+
94
+ LIBC = libc_so
95
+ LIBM = libm_so
96
+ end
97
+ end
@@ -0,0 +1,85 @@
1
+ require "fiddle/import"
2
+
3
+ module Fiddley
4
+ class MemoryPointer
5
+ def initialize(type, num = 1)
6
+ size = Fiddley.type2size(type) * num
7
+ @ptr = Fiddle::Pointer.malloc(size)
8
+ end
9
+
10
+ def write_int16(val)
11
+ @ptr[0, 2] = [val].pack('s')
12
+ end
13
+
14
+ def write_int32(val)
15
+ @ptr[0, 4] = [val].pack('l')
16
+ end
17
+
18
+ def write_array_of_uint32(ary)
19
+ write_string(ary.pack('L*'))
20
+ end
21
+
22
+ def write_string(str)
23
+ @ptr[0, str.bytesize] = str
24
+ end
25
+
26
+ def read_bytes(size)
27
+ @ptr[0, size]
28
+ end
29
+
30
+ def read_int8
31
+ get_int8(0)
32
+ end
33
+
34
+ def read_uint8
35
+ get_uint8(0)
36
+ end
37
+
38
+ def read_int16
39
+ get_int16(0)
40
+ end
41
+
42
+ def read_uint16
43
+ get_uint16(0)
44
+ end
45
+
46
+ def read_int32
47
+ get_int32(0)
48
+ end
49
+
50
+ def read_uint32
51
+ get_uint32(0)
52
+ end
53
+
54
+ def get_int8(offset)
55
+ @ptr[offset, 1].unpack1('c')
56
+ end
57
+
58
+ def get_uint8(offset)
59
+ @ptr[offset, 1].unpack1('C')
60
+ end
61
+
62
+ def get_int16(offset)
63
+ @ptr[offset, 2].unpack1('s')
64
+ end
65
+
66
+ def get_uint16(offset)
67
+ @ptr[offset, 2].unpack1('S')
68
+ end
69
+
70
+ def get_int32(offset)
71
+ @ptr[offset, 4].unpack1('l')
72
+ end
73
+
74
+ def get_uint32(offset)
75
+ @ptr[offset, 4].unpack1('L')
76
+ end
77
+
78
+ alias read_int read_int32
79
+ alias get_int get_int32
80
+
81
+ def to_ptr
82
+ @ptr
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,52 @@
1
+ require "fiddle/import"
2
+
3
+ module Fiddley
4
+ class Struct
5
+ def self.layout(*args)
6
+ @members = {}
7
+ @size = 0
8
+ args.each_slice(2) do |name, type|
9
+ @members[name] = [type, @size]
10
+ @size += Fiddley.type2size(type)
11
+ end
12
+ end
13
+
14
+ def self.ptr
15
+ :pointer
16
+ end
17
+
18
+ def self.members
19
+ @members
20
+ end
21
+
22
+ def self.size
23
+ @size
24
+ end
25
+
26
+ def self.offset_of(key)
27
+ raise IndexError, "#{key} is not defined" unless members.has_key?(key)
28
+ type, offset = members[key]
29
+ offset
30
+ end
31
+
32
+ def initialize
33
+ @ptr = Fiddle::Pointer.malloc(self.class.size)
34
+ end
35
+
36
+ def [](key)
37
+ raise IndexError, "#{key} is not defined" unless self.class.members.has_key?(key)
38
+ type, offset = self.class.members[key]
39
+ Fiddley.str2value(type, @ptr[offset, Fiddley.type2size(type)])
40
+ end
41
+
42
+ def []=(key, value)
43
+ raise IndexError, "#{key} is not defined" unless self.class.members.has_key?(key)
44
+ type, offset = self.class.members[key]
45
+ @ptr[offset, Fiddley.type2size(type)] = Fiddley.value2str(type, value)
46
+ end
47
+
48
+ def to_ptr
49
+ @ptr
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,81 @@
1
+ module Fiddley
2
+ def self.type2size(type)
3
+ case type
4
+ when :char, :uchar, :int8, :uint8
5
+ 1
6
+ when :short, :ushort, :int16, :uint16
7
+ 2
8
+ when :int, :uint, :int32, :uint32
9
+ 4
10
+ when :long, :ulong, :int64, :uint64
11
+ 8
12
+ when :string, :pointer
13
+ 8
14
+ else
15
+ raise TypeError, "unknown type #{type}"
16
+ end
17
+ end
18
+
19
+ def self.str2value(type, str)
20
+ case type
21
+ when :char, :uchar, :int8, :uint8
22
+ str.unpack1('c')
23
+ when :short, :ushort, :int16, :uint16
24
+ str.unpack1('s')
25
+ when :int, :uint, :int32, :uint32
26
+ str.unpack1('l')
27
+ when :long, :ulong, :int64, :uint64
28
+ str.unpack1('Q')
29
+ when :string, :pointer
30
+ str.unpack1('p')
31
+ else
32
+ raise TypeError, "unknown type #{type}"
33
+ end
34
+ end
35
+
36
+ def self.value2str(type, value)
37
+ case type
38
+ when :char, :uchar, :int8, :uint8
39
+ [value].pack('c')
40
+ when :short, :ushort, :int16, :uint16
41
+ [value].pack('s')
42
+ when :int, :uint, :int32, :uint32
43
+ [value].pack('l')
44
+ when :long, :ulong, :int64, :uint64
45
+ [value].pack('Q')
46
+ when :string, :pointer
47
+ [value].pack('p')
48
+ else
49
+ raise TypeError, "unknown type #{type}"
50
+ end
51
+ end
52
+
53
+ def self.type2str(type)
54
+ case type
55
+ when :char, :int8
56
+ "char"
57
+ when :uchar, :uint8
58
+ "unsigned char"
59
+ when :short, :int16
60
+ "short"
61
+ when :ushort, :uint16
62
+ "unsigned short"
63
+ when :int, :int32
64
+ "int"
65
+ when :uint, :uint32
66
+ "unsigned int"
67
+ when :long, :int64
68
+ "long"
69
+ when :ulong, :uint64
70
+ "unsigned long"
71
+ when :long_long
72
+ "long long"
73
+ when :ulong_long
74
+ "unsigned long long"
75
+ when :string, :pointer
76
+ "void *"
77
+ else
78
+ type.to_s
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,9 @@
1
+ require "ffi"
2
+
3
+ module Hello
4
+ extend FFI::Library
5
+ ffi_lib FFI::Library::LIBC
6
+ attach_function :puts, [:string], :int
7
+ end
8
+
9
+ Hello.puts("Hello, world")
@@ -0,0 +1,13 @@
1
+ require 'ffi'
2
+
3
+ module HelloWin
4
+ extend FFI::Library
5
+
6
+ ffi_lib 'user32'
7
+ ffi_convention :stdcall
8
+
9
+ attach_function :message_box, :MessageBoxA,[ :pointer, :string, :string, :uint ], :int
10
+ end
11
+
12
+ rc = HelloWin.message_box nil, 'Hello Windows!', 'FFI on Windows', 1
13
+ puts "Return code: #{rc}"
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fiddley
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - U.Nakamura
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Use Fiddle instead of Ruby-FFI !!!
14
+ email:
15
+ - usa@garbagecollect.jp
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.md
21
+ - Rakefile
22
+ - fiddley.gemspec
23
+ - lib/ffi.rb
24
+ - lib/fiddley.rb
25
+ - lib/fiddley/function.rb
26
+ - lib/fiddley/library.rb
27
+ - lib/fiddley/memory_pointer.rb
28
+ - lib/fiddley/struct.rb
29
+ - lib/fiddley/utils.rb
30
+ - test/sample.rb
31
+ - test/sample2.rb
32
+ homepage: https://github.com/unak/fiddley
33
+ licenses:
34
+ - BSD-2-Clause
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 2.6.11
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: FFI compatible interface for Fiddle
56
+ test_files: []