c2ffi4rb 0.0.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.
- checksums.yaml +7 -0
- data/README.md +31 -0
- data/exe/c2ffi4rb +36 -0
- data/lib/c2ffi4rb/parser.rb +188 -0
- data/lib/c2ffi4rb/version.rb +3 -0
- data/lib/c2ffi4rb.rb +7 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 86a593339fb44c53b753ecbae5120b0d3cd67363f8899b8122fa100f800d1fcc
|
4
|
+
data.tar.gz: c2a2c0ab90ce7e1307d706b268778267237691a56ce71491bfe2503b27b3f8c8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 42260432b9a7267183c23e4ab79303257e25445c5ea5be46bcf61d7d27b43e8283144741bcf6eb95a9fd66ac7e3094067e68165648fa6fe13594459b588670f4
|
7
|
+
data.tar.gz: '08281db0ccbaedba8fb39908f343c69dbe348da5e8e49071ded01c382468962b84b308b59c6a57c707586a94dba6b5fb86937d48e0c3a1f37486ae1b52b29bdd'
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# c2ffi4rb
|
2
|
+
|
3
|
+
[c2ffi](https://github.com/rpav/c2ffi) - FFI binding generator - for Ruby
|
4
|
+
|
5
|
+
# installation
|
6
|
+
|
7
|
+
```sh
|
8
|
+
gem install c2ffi4rb
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
First, produce a `spec` file using `c2ffi`:
|
14
|
+
|
15
|
+
```sh
|
16
|
+
c2ffi -M macros.h -o example.json example.h
|
17
|
+
c2ffi -o macros.json macros.h
|
18
|
+
```
|
19
|
+
|
20
|
+
Now you can generate a file manually with the included tool,
|
21
|
+
`c2ffi-ruby`, as follows:
|
22
|
+
|
23
|
+
```sh
|
24
|
+
c2ffi4rb example.json macro.json > simple.rb
|
25
|
+
```
|
26
|
+
|
27
|
+
This produces the `simple.rb` file, as included.
|
28
|
+
|
29
|
+
## Licence
|
30
|
+
|
31
|
+
- [LGPL-2](https://github.com/rpav/c2ffi-ruby/blob/master/c2ffi-ruby.gemspec)
|
data/exe/c2ffi4rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
## This is meant to be more of an unsophisticated demo than a
|
5
|
+
## production tool. Generating spec and ruby files should be part of
|
6
|
+
## your build system. But this is how you can use it.
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
require 'json'
|
10
|
+
require 'c2ffi4rb'
|
11
|
+
|
12
|
+
options = {}
|
13
|
+
|
14
|
+
Version = C2FFI4RB::VERSION # Fixme
|
15
|
+
|
16
|
+
opts = OptionParser.new
|
17
|
+
opts.banner = 'Usage: c2ffi4rb [options] [file1, file2, ...]'
|
18
|
+
opts.on('-h', '--help', 'Show this message') do
|
19
|
+
puts opts
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
opts.parse!
|
23
|
+
|
24
|
+
if ARGV.empty?
|
25
|
+
warn opts
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
spec = []
|
30
|
+
ARGV.each do |file|
|
31
|
+
File.open(file) do |io|
|
32
|
+
spec += JSON.parse(io.read, Hash[:symbolize_names, true])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
C2FFI4RB::Parser.parse(spec)
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module C2FFI4RB
|
4
|
+
class Parser
|
5
|
+
TYPE_TABLE = {
|
6
|
+
"unsigned-int": :uint,
|
7
|
+
"unsigned-char": :uchar,
|
8
|
+
"unsigned-long": :ulong,
|
9
|
+
"function-pointer": :pointer
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
def self.parse(arr)
|
13
|
+
Parser.new.parse(arr)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@struct_type = {}
|
18
|
+
@toplevels = []
|
19
|
+
@anon_counter = 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(arr)
|
23
|
+
arr.each do |form|
|
24
|
+
s = parse_toplevel(form)
|
25
|
+
@toplevels << s if s
|
26
|
+
end
|
27
|
+
|
28
|
+
@toplevels.each do |t|
|
29
|
+
puts
|
30
|
+
case t
|
31
|
+
when String
|
32
|
+
puts "#{t}"
|
33
|
+
when Array
|
34
|
+
t.each do |l|
|
35
|
+
puts "#{l}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_toplevel(form)
|
44
|
+
case form[:tag]
|
45
|
+
when 'typedef'
|
46
|
+
type = parse_type(form[:type])
|
47
|
+
|
48
|
+
# I don't think typedef works right with structs, so assign
|
49
|
+
if @struct_type[type]
|
50
|
+
name = add_struct(form[:name])
|
51
|
+
"#{name} = #{type}"
|
52
|
+
else
|
53
|
+
"typedef #{type}, :#{form[:name]}"
|
54
|
+
end
|
55
|
+
|
56
|
+
when 'const'
|
57
|
+
type = parse_type(form[:type])
|
58
|
+
if type == ':string'
|
59
|
+
"#{form[:name].upcase} = \"#{form[:value]}\""
|
60
|
+
else
|
61
|
+
"#{form[:name].upcase} = #{form[:value]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
when 'extern'
|
65
|
+
'attach_variable ' \
|
66
|
+
":#{form[:name]}, :#{form[:name]}, #{parse_type(form[:type])}"
|
67
|
+
|
68
|
+
when 'function'
|
69
|
+
s = []
|
70
|
+
s << "attach_function '#{form[:name]}', ["
|
71
|
+
form[:parameters].each do |f|
|
72
|
+
s << " #{parse_type(f[:type])},"
|
73
|
+
end
|
74
|
+
s << "], #{parse_type(form['return-type'.intern])}"
|
75
|
+
# emacs doesn't like :"foo" ---^
|
76
|
+
|
77
|
+
when 'struct', 'union'
|
78
|
+
name = add_struct(form[:name])
|
79
|
+
make_struct(form)
|
80
|
+
|
81
|
+
when 'enum'
|
82
|
+
name = add_enum(form[:name])
|
83
|
+
s = []
|
84
|
+
s << "enum #{name}, ["
|
85
|
+
form[:fields].each do |f|
|
86
|
+
s << " :#{f[:name]}, #{f[:value]},"
|
87
|
+
end
|
88
|
+
s << ']'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_struct(name)
|
93
|
+
if name == ''
|
94
|
+
@anon_counter += 1
|
95
|
+
name = 'Anon_Type_' + @anon_counter.to_s
|
96
|
+
return name
|
97
|
+
end
|
98
|
+
|
99
|
+
name = 'C' + name if name.start_with? '_'
|
100
|
+
|
101
|
+
name = name.capitalize.gsub!(/_([a-z])/) { |m| "_#{m[1].upcase}" }
|
102
|
+
@struct_type[name] = true
|
103
|
+
name
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_enum(name)
|
107
|
+
if name == ''
|
108
|
+
@anon_counter += 1
|
109
|
+
name = ':anon_type_' + @anon_counter.to_s
|
110
|
+
return name
|
111
|
+
end
|
112
|
+
|
113
|
+
if name[0] != ':'
|
114
|
+
":#{name}"
|
115
|
+
else
|
116
|
+
name
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def make_struct(form)
|
121
|
+
name = add_struct(form[:name])
|
122
|
+
|
123
|
+
type = if form[:tag] == ':struct'
|
124
|
+
'FFI::Struct'
|
125
|
+
else
|
126
|
+
'FFI::Union'
|
127
|
+
end
|
128
|
+
|
129
|
+
s = []
|
130
|
+
s << "class #{name} < #{type}"
|
131
|
+
|
132
|
+
if form[:fields].length.positive?
|
133
|
+
s << ' layout \\'
|
134
|
+
size = form[:fields].length
|
135
|
+
sep = ','
|
136
|
+
form[:fields].each_with_index do |f, i|
|
137
|
+
sep = '' if i >= (size - 1)
|
138
|
+
s << " :#{f[:name]}, #{parse_type(f[:type])}#{sep}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
s << 'end'
|
142
|
+
end
|
143
|
+
|
144
|
+
def parse_type(form)
|
145
|
+
tt = TYPE_TABLE[form[:tag]]
|
146
|
+
return tt if tt
|
147
|
+
|
148
|
+
case form[:tag]
|
149
|
+
when ':pointer'
|
150
|
+
pointee = parse_type(form[:type])
|
151
|
+
if [':char', ':uchar'].include?(pointee)
|
152
|
+
':string'
|
153
|
+
elsif @struct_type[pointee]
|
154
|
+
"#{@struct_type[pointee]}.ptr"
|
155
|
+
else
|
156
|
+
':pointer'
|
157
|
+
end
|
158
|
+
|
159
|
+
when ':array'
|
160
|
+
"[#{parse_type(form[:type])}, #{form[:size]}]"
|
161
|
+
|
162
|
+
when ':struct', ':union'
|
163
|
+
add_struct(form[:name])
|
164
|
+
|
165
|
+
when ':enum'
|
166
|
+
add_enum(form[:name])
|
167
|
+
|
168
|
+
when 'enum'
|
169
|
+
form[:name] = add_enum(form[:name])
|
170
|
+
parse_toplevel(form)
|
171
|
+
form[:name]
|
172
|
+
|
173
|
+
when 'struct', 'union'
|
174
|
+
form[:name] = add_struct(form[:name])
|
175
|
+
parse_toplevel(form)
|
176
|
+
form[:name]
|
177
|
+
|
178
|
+
else
|
179
|
+
# All non-Classy types are :-prefixed?
|
180
|
+
if form[:tag][0] != ':'
|
181
|
+
":#{form[:tag]}"
|
182
|
+
else
|
183
|
+
form[:tag]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
data/lib/c2ffi4rb.rb
ADDED
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: c2ffi4rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kojix2
|
8
|
+
- Ryan Pavlik
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2023-09-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rake
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: Import C2FFI JSON to ruby/ffi
|
57
|
+
email:
|
58
|
+
- 2xijok@gmail.com
|
59
|
+
- rpavlik@gmail.com
|
60
|
+
executables:
|
61
|
+
- c2ffi4rb
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- README.md
|
66
|
+
- exe/c2ffi4rb
|
67
|
+
- lib/c2ffi4rb.rb
|
68
|
+
- lib/c2ffi4rb/parser.rb
|
69
|
+
- lib/c2ffi4rb/version.rb
|
70
|
+
homepage: https://github.com/kojix2/c2ffi4rb
|
71
|
+
licenses:
|
72
|
+
- LGPL-2
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubygems_version: 3.4.10
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: C2FFI for Ruby-FFI
|
93
|
+
test_files: []
|