fiddley 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +38 -0
- data/Rakefile +10 -0
- data/fiddley.gemspec +20 -0
- data/lib/ffi.rb +1 -0
- data/lib/fiddley.rb +11 -0
- data/lib/fiddley/function.rb +13 -0
- data/lib/fiddley/library.rb +97 -0
- data/lib/fiddley/memory_pointer.rb +85 -0
- data/lib/fiddley/struct.rb +52 -0
- data/lib/fiddley/utils.rb +81 -0
- data/test/sample.rb +9 -0
- data/test/sample2.rb +13 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -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
|
data/README.md
ADDED
@@ -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
|
+
|
data/Rakefile
ADDED
data/fiddley.gemspec
ADDED
@@ -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
|
data/lib/ffi.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "fiddley"
|
data/lib/fiddley.rb
ADDED
@@ -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
|
data/test/sample.rb
ADDED
data/test/sample2.rb
ADDED
@@ -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: []
|