fiddle 1.0.0.beta1
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/.gitignore +12 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/fiddle/closure.c +345 -0
- data/ext/fiddle/closure.h +8 -0
- data/ext/fiddle/conversions.c +141 -0
- data/ext/fiddle/conversions.h +44 -0
- data/ext/fiddle/extconf.rb +183 -0
- data/ext/fiddle/extlibs +2 -0
- data/ext/fiddle/fiddle.c +454 -0
- data/ext/fiddle/fiddle.h +138 -0
- data/ext/fiddle/function.c +315 -0
- data/ext/fiddle/function.h +8 -0
- data/ext/fiddle/handle.c +479 -0
- data/ext/fiddle/pointer.c +721 -0
- data/ext/fiddle/win32/fficonfig.h +29 -0
- data/ext/fiddle/win32/libffi-3.2.1-mswin.patch +191 -0
- data/ext/fiddle/win32/libffi-config.rb +48 -0
- data/ext/fiddle/win32/libffi.mk.tmpl +96 -0
- data/fiddle.gemspec +23 -0
- data/lib/fiddle.rb +56 -0
- data/lib/fiddle/closure.rb +49 -0
- data/lib/fiddle/cparser.rb +194 -0
- data/lib/fiddle/function.rb +18 -0
- data/lib/fiddle/import.rb +318 -0
- data/lib/fiddle/pack.rb +129 -0
- data/lib/fiddle/struct.rb +244 -0
- data/lib/fiddle/types.rb +72 -0
- data/lib/fiddle/value.rb +113 -0
- metadata +136 -0
@@ -0,0 +1,141 @@
|
|
1
|
+
#include <fiddle.h>
|
2
|
+
|
3
|
+
ffi_type *
|
4
|
+
int_to_ffi_type(int type)
|
5
|
+
{
|
6
|
+
int signed_p = 1;
|
7
|
+
|
8
|
+
if (type < 0) {
|
9
|
+
type = -1 * type;
|
10
|
+
signed_p = 0;
|
11
|
+
}
|
12
|
+
|
13
|
+
#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t)
|
14
|
+
|
15
|
+
switch (type) {
|
16
|
+
case TYPE_VOID:
|
17
|
+
return &ffi_type_void;
|
18
|
+
case TYPE_VOIDP:
|
19
|
+
return &ffi_type_pointer;
|
20
|
+
case TYPE_CHAR:
|
21
|
+
return rb_ffi_type_of(char);
|
22
|
+
case TYPE_SHORT:
|
23
|
+
return rb_ffi_type_of(short);
|
24
|
+
case TYPE_INT:
|
25
|
+
return rb_ffi_type_of(int);
|
26
|
+
case TYPE_LONG:
|
27
|
+
return rb_ffi_type_of(long);
|
28
|
+
#if HAVE_LONG_LONG
|
29
|
+
case TYPE_LONG_LONG:
|
30
|
+
return rb_ffi_type_of(long_long);
|
31
|
+
#endif
|
32
|
+
case TYPE_FLOAT:
|
33
|
+
return &ffi_type_float;
|
34
|
+
case TYPE_DOUBLE:
|
35
|
+
return &ffi_type_double;
|
36
|
+
default:
|
37
|
+
rb_raise(rb_eRuntimeError, "unknown type %d", type);
|
38
|
+
}
|
39
|
+
return &ffi_type_pointer;
|
40
|
+
}
|
41
|
+
|
42
|
+
void
|
43
|
+
value_to_generic(int type, VALUE src, fiddle_generic * dst)
|
44
|
+
{
|
45
|
+
switch (type) {
|
46
|
+
case TYPE_VOID:
|
47
|
+
break;
|
48
|
+
case TYPE_VOIDP:
|
49
|
+
dst->pointer = NUM2PTR(rb_Integer(src));
|
50
|
+
break;
|
51
|
+
case TYPE_CHAR:
|
52
|
+
dst->schar = (signed char)NUM2INT(src);
|
53
|
+
break;
|
54
|
+
case -TYPE_CHAR:
|
55
|
+
dst->uchar = (unsigned char)NUM2UINT(src);
|
56
|
+
break;
|
57
|
+
case TYPE_SHORT:
|
58
|
+
dst->sshort = (unsigned short)NUM2INT(src);
|
59
|
+
break;
|
60
|
+
case -TYPE_SHORT:
|
61
|
+
dst->sshort = (signed short)NUM2UINT(src);
|
62
|
+
break;
|
63
|
+
case TYPE_INT:
|
64
|
+
dst->sint = NUM2INT(src);
|
65
|
+
break;
|
66
|
+
case -TYPE_INT:
|
67
|
+
dst->uint = NUM2UINT(src);
|
68
|
+
break;
|
69
|
+
case TYPE_LONG:
|
70
|
+
dst->slong = NUM2LONG(src);
|
71
|
+
break;
|
72
|
+
case -TYPE_LONG:
|
73
|
+
dst->ulong = NUM2ULONG(src);
|
74
|
+
break;
|
75
|
+
#if HAVE_LONG_LONG
|
76
|
+
case TYPE_LONG_LONG:
|
77
|
+
dst->slong_long = NUM2LL(src);
|
78
|
+
break;
|
79
|
+
case -TYPE_LONG_LONG:
|
80
|
+
dst->ulong_long = NUM2ULL(src);
|
81
|
+
break;
|
82
|
+
#endif
|
83
|
+
case TYPE_FLOAT:
|
84
|
+
dst->ffloat = (float)NUM2DBL(src);
|
85
|
+
break;
|
86
|
+
case TYPE_DOUBLE:
|
87
|
+
dst->ddouble = NUM2DBL(src);
|
88
|
+
break;
|
89
|
+
default:
|
90
|
+
rb_raise(rb_eRuntimeError, "unknown type %d", type);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
VALUE
|
95
|
+
generic_to_value(VALUE rettype, fiddle_generic retval)
|
96
|
+
{
|
97
|
+
int type = NUM2INT(rettype);
|
98
|
+
VALUE cPointer;
|
99
|
+
|
100
|
+
cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
|
101
|
+
|
102
|
+
switch (type) {
|
103
|
+
case TYPE_VOID:
|
104
|
+
return Qnil;
|
105
|
+
case TYPE_VOIDP:
|
106
|
+
return rb_funcall(cPointer, rb_intern("[]"), 1,
|
107
|
+
PTR2NUM((void *)retval.pointer));
|
108
|
+
case TYPE_CHAR:
|
109
|
+
return INT2NUM((signed char)retval.fffi_sarg);
|
110
|
+
case -TYPE_CHAR:
|
111
|
+
return INT2NUM((unsigned char)retval.fffi_arg);
|
112
|
+
case TYPE_SHORT:
|
113
|
+
return INT2NUM((signed short)retval.fffi_sarg);
|
114
|
+
case -TYPE_SHORT:
|
115
|
+
return INT2NUM((unsigned short)retval.fffi_arg);
|
116
|
+
case TYPE_INT:
|
117
|
+
return INT2NUM((signed int)retval.fffi_sarg);
|
118
|
+
case -TYPE_INT:
|
119
|
+
return UINT2NUM((unsigned int)retval.fffi_arg);
|
120
|
+
case TYPE_LONG:
|
121
|
+
return LONG2NUM(retval.slong);
|
122
|
+
case -TYPE_LONG:
|
123
|
+
return ULONG2NUM(retval.ulong);
|
124
|
+
#if HAVE_LONG_LONG
|
125
|
+
case TYPE_LONG_LONG:
|
126
|
+
return LL2NUM(retval.slong_long);
|
127
|
+
case -TYPE_LONG_LONG:
|
128
|
+
return ULL2NUM(retval.ulong_long);
|
129
|
+
#endif
|
130
|
+
case TYPE_FLOAT:
|
131
|
+
return rb_float_new(retval.ffloat);
|
132
|
+
case TYPE_DOUBLE:
|
133
|
+
return rb_float_new(retval.ddouble);
|
134
|
+
default:
|
135
|
+
rb_raise(rb_eRuntimeError, "unknown type %d", type);
|
136
|
+
}
|
137
|
+
|
138
|
+
UNREACHABLE;
|
139
|
+
}
|
140
|
+
|
141
|
+
/* vim: set noet sw=4 sts=4 */
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#ifndef FIDDLE_CONVERSIONS_H
|
2
|
+
#define FIDDLE_CONVERSIONS_H
|
3
|
+
|
4
|
+
#include <fiddle.h>
|
5
|
+
|
6
|
+
typedef union
|
7
|
+
{
|
8
|
+
ffi_arg fffi_arg; /* rvalue smaller than unsigned long */
|
9
|
+
ffi_sarg fffi_sarg; /* rvalue smaller than signed long */
|
10
|
+
unsigned char uchar; /* ffi_type_uchar */
|
11
|
+
signed char schar; /* ffi_type_schar */
|
12
|
+
unsigned short ushort; /* ffi_type_sshort */
|
13
|
+
signed short sshort; /* ffi_type_ushort */
|
14
|
+
unsigned int uint; /* ffi_type_uint */
|
15
|
+
signed int sint; /* ffi_type_sint */
|
16
|
+
unsigned long ulong; /* ffi_type_ulong */
|
17
|
+
signed long slong; /* ffi_type_slong */
|
18
|
+
float ffloat; /* ffi_type_float */
|
19
|
+
double ddouble; /* ffi_type_double */
|
20
|
+
#if HAVE_LONG_LONG
|
21
|
+
unsigned LONG_LONG ulong_long; /* ffi_type_ulong_long */
|
22
|
+
signed LONG_LONG slong_long; /* ffi_type_ulong_long */
|
23
|
+
#endif
|
24
|
+
void * pointer; /* ffi_type_pointer */
|
25
|
+
} fiddle_generic;
|
26
|
+
|
27
|
+
ffi_type * int_to_ffi_type(int type);
|
28
|
+
void value_to_generic(int type, VALUE src, fiddle_generic * dst);
|
29
|
+
VALUE generic_to_value(VALUE rettype, fiddle_generic retval);
|
30
|
+
|
31
|
+
#define VALUE2GENERIC(_type, _src, _dst) value_to_generic((_type), (_src), (_dst))
|
32
|
+
#define INT2FFI_TYPE(_type) int_to_ffi_type(_type)
|
33
|
+
#define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_retval))
|
34
|
+
|
35
|
+
#if SIZEOF_VOIDP == SIZEOF_LONG
|
36
|
+
# define PTR2NUM(x) (LONG2NUM((long)(x)))
|
37
|
+
# define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
|
38
|
+
#else
|
39
|
+
/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */
|
40
|
+
# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x)))
|
41
|
+
# define NUM2PTR(x) ((void*)(NUM2ULL(x)))
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#endif
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'mkmf'
|
3
|
+
|
4
|
+
# :stopdoc:
|
5
|
+
|
6
|
+
bundle = enable_config('bundled-libffi')
|
7
|
+
if ! bundle
|
8
|
+
dir_config 'libffi'
|
9
|
+
|
10
|
+
pkg_config("libffi") and
|
11
|
+
ver = pkg_config("libffi", "modversion")
|
12
|
+
|
13
|
+
if have_header(ffi_header = 'ffi.h')
|
14
|
+
true
|
15
|
+
elsif have_header(ffi_header = 'ffi/ffi.h')
|
16
|
+
$defs.push(format('-DUSE_HEADER_HACKS'))
|
17
|
+
true
|
18
|
+
end and (have_library('ffi') || have_library('libffi'))
|
19
|
+
end or
|
20
|
+
begin
|
21
|
+
ver = bundle != false &&
|
22
|
+
Dir.glob("#{$srcdir}/libffi-*/")
|
23
|
+
.map {|n| File.basename(n)}
|
24
|
+
.max_by {|n| n.scan(/\d+/).map(&:to_i)}
|
25
|
+
unless ver
|
26
|
+
raise "missing libffi. Please install libffi."
|
27
|
+
end
|
28
|
+
|
29
|
+
srcdir = "#{$srcdir}/#{ver}"
|
30
|
+
ffi_header = 'ffi.h'
|
31
|
+
libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new
|
32
|
+
libffi.dir = ver
|
33
|
+
if $srcdir == "."
|
34
|
+
libffi.builddir = "#{ver}/#{RUBY_PLATFORM}"
|
35
|
+
libffi.srcdir = "."
|
36
|
+
else
|
37
|
+
libffi.builddir = libffi.dir
|
38
|
+
libffi.srcdir = relative_from(srcdir, "..")
|
39
|
+
end
|
40
|
+
libffi.include = "#{libffi.builddir}/include"
|
41
|
+
libffi.lib = "#{libffi.builddir}/.libs"
|
42
|
+
libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}"
|
43
|
+
nowarn = CONFIG.merge("warnflags"=>"")
|
44
|
+
libffi.cflags = RbConfig.expand("$(CFLAGS)", nowarn)
|
45
|
+
ver = ver[/libffi-(.*)/, 1]
|
46
|
+
|
47
|
+
FileUtils.mkdir_p(libffi.dir)
|
48
|
+
libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1]
|
49
|
+
libffi.ldflags = RbConfig.expand("$(LDFLAGS) #{libpathflag([relative_from($topdir, "..")])} #{$LIBRUBYARG}")
|
50
|
+
libffi.arch = RbConfig::CONFIG['host']
|
51
|
+
if $mswin
|
52
|
+
unless find_executable(as = /x64/ =~ libffi.arch ? "ml64" : "ml")
|
53
|
+
raise "missing #{as} command."
|
54
|
+
end
|
55
|
+
$defs << "-DFFI_BUILDING"
|
56
|
+
libffi_config = "#{relative_from($srcdir, '..')}/win32/libffi-config.rb"
|
57
|
+
config = CONFIG.merge("top_srcdir" => $top_srcdir)
|
58
|
+
args = $ruby.gsub(/:\/=\\/, '')
|
59
|
+
args.gsub!(/\)\\/, ')/')
|
60
|
+
args = args.shellsplit
|
61
|
+
args.map! {|s| RbConfig.expand(s, config)}
|
62
|
+
args << '-C' << libffi.dir << libffi_config
|
63
|
+
opts = {}
|
64
|
+
else
|
65
|
+
args = %W[sh #{libffi.srcdir}/configure ]
|
66
|
+
opts = {chdir: libffi.dir}
|
67
|
+
end
|
68
|
+
cc = RbConfig::CONFIG['CC']
|
69
|
+
cxx = RbConfig::CONFIG['CXX']
|
70
|
+
ld = RbConfig::CONFIG['LD']
|
71
|
+
args.concat %W[
|
72
|
+
--srcdir=#{libffi.srcdir}
|
73
|
+
--host=#{libffi.arch}
|
74
|
+
--enable-builddir=#{RUBY_PLATFORM}
|
75
|
+
]
|
76
|
+
args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static')
|
77
|
+
args << libffi.opt if libffi.opt
|
78
|
+
args.concat %W[
|
79
|
+
CC=#{cc} CFLAGS=#{libffi.cflags}
|
80
|
+
CXX=#{cxx} CXXFLAGS=#{RbConfig.expand("$(CXXFLAGS)", nowarn)}
|
81
|
+
LD=#{ld} LDFLAGS=#{libffi.ldflags}
|
82
|
+
]
|
83
|
+
|
84
|
+
FileUtils.rm_f("#{libffi.include}/ffitarget.h")
|
85
|
+
Logging::open do
|
86
|
+
Logging.message("%p in %p\n", args, opts)
|
87
|
+
unless system(*args, **opts)
|
88
|
+
begin
|
89
|
+
IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile))
|
90
|
+
rescue SystemCallError => e
|
91
|
+
Logfile.message("%s\n", e.message)
|
92
|
+
end
|
93
|
+
raise "failed to configure libffi. Please install libffi."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
if $mswin && File.file?("#{libffi.include}/ffitarget.h")
|
97
|
+
FileUtils.rm_f("#{libffi.include}/ffitarget.h")
|
98
|
+
end
|
99
|
+
unless File.file?("#{libffi.include}/ffitarget.h")
|
100
|
+
FileUtils.cp("#{srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true)
|
101
|
+
end
|
102
|
+
$INCFLAGS << " -I" << libffi.include
|
103
|
+
end
|
104
|
+
|
105
|
+
if ver
|
106
|
+
ver = ver.gsub(/-rc\d+/, '') # If ver contains rc version, just ignored.
|
107
|
+
ver = (ver.split('.') + [0,0])[0,3]
|
108
|
+
$defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % ver }})
|
109
|
+
end
|
110
|
+
|
111
|
+
have_header 'sys/mman.h'
|
112
|
+
|
113
|
+
if have_header "dlfcn.h"
|
114
|
+
have_library "dl"
|
115
|
+
|
116
|
+
%w{ dlopen dlclose dlsym }.each do |func|
|
117
|
+
abort "missing function #{func}" unless have_func(func)
|
118
|
+
end
|
119
|
+
|
120
|
+
have_func "dlerror"
|
121
|
+
elsif have_header "windows.h"
|
122
|
+
%w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
|
123
|
+
abort "missing function #{func}" unless have_func(func)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
have_const('FFI_STDCALL', ffi_header)
|
128
|
+
|
129
|
+
config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h")))
|
130
|
+
types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil}
|
131
|
+
types.each do |type, signed|
|
132
|
+
if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config
|
133
|
+
if size = $2 and size != 'VOIDP'
|
134
|
+
size = types.fetch(size) {size}
|
135
|
+
$defs << format("-DTYPE_%s=TYPE_%s", signed||type, size)
|
136
|
+
end
|
137
|
+
if signed
|
138
|
+
check_signedness(type.downcase, "stddef.h")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
if libffi
|
144
|
+
$LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
|
145
|
+
$INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
|
146
|
+
end
|
147
|
+
$INCFLAGS << " -I$(top_srcdir)"
|
148
|
+
create_makefile 'fiddle' do |conf|
|
149
|
+
if !libffi
|
150
|
+
next conf << "LIBFFI_CLEAN = none\n"
|
151
|
+
elsif $gnumake && !$nmake
|
152
|
+
submake_arg = "-C $(LIBFFI_DIR)\n"
|
153
|
+
else
|
154
|
+
submake_pre = "cd $(LIBFFI_DIR) && #{config_string("exec")}".strip
|
155
|
+
end
|
156
|
+
if $nmake
|
157
|
+
cmd = "$(RUBY) -C $(LIBFFI_DIR) #{libffi_config} --srcdir=$(LIBFFI_SRCDIR)"
|
158
|
+
else
|
159
|
+
cmd = "cd $(LIBFFI_DIR) && #$exec $(LIBFFI_SRCDIR)/configure #{libffi.opt}"
|
160
|
+
end
|
161
|
+
sep = "/"
|
162
|
+
seprpl = config_string('BUILD_FILE_SEPARATOR') {|s| sep = s; ":/=#{s}" if s != "/"} || ""
|
163
|
+
conf << <<-MK.gsub(/^ +| +$/, '')
|
164
|
+
PWD =
|
165
|
+
LIBFFI_CONFIGURE = #{cmd}
|
166
|
+
LIBFFI_ARCH = #{libffi.arch}
|
167
|
+
LIBFFI_SRCDIR = #{libffi.srcdir.sub(libffi.dir, '$(LIBFFI_DIR)')}
|
168
|
+
LIBFFI_DIR = #{libffi.dir}
|
169
|
+
LIBFFI_A = #{libffi.a.sub(libffi.dir, '$(LIBFFI_DIR)')}
|
170
|
+
LIBFFI_CFLAGS = #{libffi.cflags}
|
171
|
+
LIBFFI_LDFLAGS = #{libffi.ldflags}
|
172
|
+
FFI_H = $(LIBFFI_DIR)/include/ffi.h
|
173
|
+
SUBMAKE_PRE = #{submake_pre}
|
174
|
+
SUBMAKE_ARG = #{submake_arg}
|
175
|
+
LIBFFI_CLEAN = libffi
|
176
|
+
MK
|
177
|
+
end
|
178
|
+
|
179
|
+
if libffi
|
180
|
+
$LIBPATH.pop
|
181
|
+
end
|
182
|
+
|
183
|
+
# :startdoc:
|
data/ext/fiddle/extlibs
ADDED
data/ext/fiddle/fiddle.c
ADDED
@@ -0,0 +1,454 @@
|
|
1
|
+
#include <fiddle.h>
|
2
|
+
|
3
|
+
VALUE mFiddle;
|
4
|
+
VALUE rb_eFiddleError;
|
5
|
+
|
6
|
+
#ifndef TYPE_SSIZE_T
|
7
|
+
# if SIZEOF_SIZE_T == SIZEOF_INT
|
8
|
+
# define TYPE_SSIZE_T TYPE_INT
|
9
|
+
# elif SIZEOF_SIZE_T == SIZEOF_LONG
|
10
|
+
# define TYPE_SSIZE_T TYPE_LONG
|
11
|
+
# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
|
12
|
+
# define TYPE_SSIZE_T TYPE_LONG_LONG
|
13
|
+
# endif
|
14
|
+
#endif
|
15
|
+
#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
|
16
|
+
|
17
|
+
#ifndef TYPE_PTRDIFF_T
|
18
|
+
# if SIZEOF_PTRDIFF_T == SIZEOF_INT
|
19
|
+
# define TYPE_PTRDIFF_T TYPE_INT
|
20
|
+
# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
|
21
|
+
# define TYPE_PTRDIFF_T TYPE_LONG
|
22
|
+
# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
|
23
|
+
# define TYPE_PTRDIFF_T TYPE_LONG_LONG
|
24
|
+
# endif
|
25
|
+
#endif
|
26
|
+
|
27
|
+
#ifndef TYPE_INTPTR_T
|
28
|
+
# if SIZEOF_INTPTR_T == SIZEOF_INT
|
29
|
+
# define TYPE_INTPTR_T TYPE_INT
|
30
|
+
# elif SIZEOF_INTPTR_T == SIZEOF_LONG
|
31
|
+
# define TYPE_INTPTR_T TYPE_LONG
|
32
|
+
# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
|
33
|
+
# define TYPE_INTPTR_T TYPE_LONG_LONG
|
34
|
+
# endif
|
35
|
+
#endif
|
36
|
+
#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
|
37
|
+
|
38
|
+
void Init_fiddle_pointer(void);
|
39
|
+
|
40
|
+
/*
|
41
|
+
* call-seq: Fiddle.malloc(size)
|
42
|
+
*
|
43
|
+
* Allocate +size+ bytes of memory and return the integer memory address
|
44
|
+
* for the allocated memory.
|
45
|
+
*/
|
46
|
+
static VALUE
|
47
|
+
rb_fiddle_malloc(VALUE self, VALUE size)
|
48
|
+
{
|
49
|
+
void *ptr;
|
50
|
+
|
51
|
+
ptr = (void*)ruby_xmalloc(NUM2SIZET(size));
|
52
|
+
return PTR2NUM(ptr);
|
53
|
+
}
|
54
|
+
|
55
|
+
/*
|
56
|
+
* call-seq: Fiddle.realloc(addr, size)
|
57
|
+
*
|
58
|
+
* Change the size of the memory allocated at the memory location +addr+ to
|
59
|
+
* +size+ bytes. Returns the memory address of the reallocated memory, which
|
60
|
+
* may be different than the address passed in.
|
61
|
+
*/
|
62
|
+
static VALUE
|
63
|
+
rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
|
64
|
+
{
|
65
|
+
void *ptr = NUM2PTR(addr);
|
66
|
+
|
67
|
+
ptr = (void*)ruby_xrealloc(ptr, NUM2SIZET(size));
|
68
|
+
return PTR2NUM(ptr);
|
69
|
+
}
|
70
|
+
|
71
|
+
/*
|
72
|
+
* call-seq: Fiddle.free(addr)
|
73
|
+
*
|
74
|
+
* Free the memory at address +addr+
|
75
|
+
*/
|
76
|
+
VALUE
|
77
|
+
rb_fiddle_free(VALUE self, VALUE addr)
|
78
|
+
{
|
79
|
+
void *ptr = NUM2PTR(addr);
|
80
|
+
|
81
|
+
ruby_xfree(ptr);
|
82
|
+
return Qnil;
|
83
|
+
}
|
84
|
+
|
85
|
+
/*
|
86
|
+
* call-seq: Fiddle.dlunwrap(addr)
|
87
|
+
*
|
88
|
+
* Returns the hexadecimal representation of a memory pointer address +addr+
|
89
|
+
*
|
90
|
+
* Example:
|
91
|
+
*
|
92
|
+
* lib = Fiddle.dlopen('/lib64/libc-2.15.so')
|
93
|
+
* => #<Fiddle::Handle:0x00000001342460>
|
94
|
+
*
|
95
|
+
* lib['strcpy'].to_s(16)
|
96
|
+
* => "7f59de6dd240"
|
97
|
+
*
|
98
|
+
* Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16)))
|
99
|
+
* => "7f59de6dd240"
|
100
|
+
*/
|
101
|
+
VALUE
|
102
|
+
rb_fiddle_ptr2value(VALUE self, VALUE addr)
|
103
|
+
{
|
104
|
+
return (VALUE)NUM2PTR(addr);
|
105
|
+
}
|
106
|
+
|
107
|
+
/*
|
108
|
+
* call-seq: Fiddle.dlwrap(val)
|
109
|
+
*
|
110
|
+
* Returns a memory pointer of a function's hexadecimal address location +val+
|
111
|
+
*
|
112
|
+
* Example:
|
113
|
+
*
|
114
|
+
* lib = Fiddle.dlopen('/lib64/libc-2.15.so')
|
115
|
+
* => #<Fiddle::Handle:0x00000001342460>
|
116
|
+
*
|
117
|
+
* Fiddle.dlwrap(lib['strcpy'].to_s(16))
|
118
|
+
* => 25522520
|
119
|
+
*/
|
120
|
+
static VALUE
|
121
|
+
rb_fiddle_value2ptr(VALUE self, VALUE val)
|
122
|
+
{
|
123
|
+
return PTR2NUM((void*)val);
|
124
|
+
}
|
125
|
+
|
126
|
+
void Init_fiddle_handle(void);
|
127
|
+
|
128
|
+
void
|
129
|
+
Init_fiddle(void)
|
130
|
+
{
|
131
|
+
/*
|
132
|
+
* Document-module: Fiddle
|
133
|
+
*
|
134
|
+
* A libffi wrapper for Ruby.
|
135
|
+
*
|
136
|
+
* == Description
|
137
|
+
*
|
138
|
+
* Fiddle is an extension to translate a foreign function interface (FFI)
|
139
|
+
* with ruby.
|
140
|
+
*
|
141
|
+
* It wraps {libffi}[http://sourceware.org/libffi/], a popular C library
|
142
|
+
* which provides a portable interface that allows code written in one
|
143
|
+
* language to call code written in another language.
|
144
|
+
*
|
145
|
+
* == Example
|
146
|
+
*
|
147
|
+
* Here we will use Fiddle::Function to wrap {floor(3) from
|
148
|
+
* libm}[http://linux.die.net/man/3/floor]
|
149
|
+
*
|
150
|
+
* require 'fiddle'
|
151
|
+
*
|
152
|
+
* libm = Fiddle.dlopen('/lib/libm.so.6')
|
153
|
+
*
|
154
|
+
* floor = Fiddle::Function.new(
|
155
|
+
* libm['floor'],
|
156
|
+
* [Fiddle::TYPE_DOUBLE],
|
157
|
+
* Fiddle::TYPE_DOUBLE
|
158
|
+
* )
|
159
|
+
*
|
160
|
+
* puts floor.call(3.14159) #=> 3.0
|
161
|
+
*
|
162
|
+
*
|
163
|
+
*/
|
164
|
+
mFiddle = rb_define_module("Fiddle");
|
165
|
+
|
166
|
+
/*
|
167
|
+
* Document-class: Fiddle::DLError
|
168
|
+
*
|
169
|
+
* standard dynamic load exception
|
170
|
+
*/
|
171
|
+
rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);
|
172
|
+
|
173
|
+
/* Document-const: TYPE_VOID
|
174
|
+
*
|
175
|
+
* C type - void
|
176
|
+
*/
|
177
|
+
rb_define_const(mFiddle, "TYPE_VOID", INT2NUM(TYPE_VOID));
|
178
|
+
|
179
|
+
/* Document-const: TYPE_VOIDP
|
180
|
+
*
|
181
|
+
* C type - void*
|
182
|
+
*/
|
183
|
+
rb_define_const(mFiddle, "TYPE_VOIDP", INT2NUM(TYPE_VOIDP));
|
184
|
+
|
185
|
+
/* Document-const: TYPE_CHAR
|
186
|
+
*
|
187
|
+
* C type - char
|
188
|
+
*/
|
189
|
+
rb_define_const(mFiddle, "TYPE_CHAR", INT2NUM(TYPE_CHAR));
|
190
|
+
|
191
|
+
/* Document-const: TYPE_SHORT
|
192
|
+
*
|
193
|
+
* C type - short
|
194
|
+
*/
|
195
|
+
rb_define_const(mFiddle, "TYPE_SHORT", INT2NUM(TYPE_SHORT));
|
196
|
+
|
197
|
+
/* Document-const: TYPE_INT
|
198
|
+
*
|
199
|
+
* C type - int
|
200
|
+
*/
|
201
|
+
rb_define_const(mFiddle, "TYPE_INT", INT2NUM(TYPE_INT));
|
202
|
+
|
203
|
+
/* Document-const: TYPE_LONG
|
204
|
+
*
|
205
|
+
* C type - long
|
206
|
+
*/
|
207
|
+
rb_define_const(mFiddle, "TYPE_LONG", INT2NUM(TYPE_LONG));
|
208
|
+
|
209
|
+
#if HAVE_LONG_LONG
|
210
|
+
/* Document-const: TYPE_LONG_LONG
|
211
|
+
*
|
212
|
+
* C type - long long
|
213
|
+
*/
|
214
|
+
rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
|
215
|
+
#endif
|
216
|
+
|
217
|
+
/* Document-const: TYPE_FLOAT
|
218
|
+
*
|
219
|
+
* C type - float
|
220
|
+
*/
|
221
|
+
rb_define_const(mFiddle, "TYPE_FLOAT", INT2NUM(TYPE_FLOAT));
|
222
|
+
|
223
|
+
/* Document-const: TYPE_DOUBLE
|
224
|
+
*
|
225
|
+
* C type - double
|
226
|
+
*/
|
227
|
+
rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE));
|
228
|
+
|
229
|
+
/* Document-const: TYPE_SIZE_T
|
230
|
+
*
|
231
|
+
* C type - size_t
|
232
|
+
*/
|
233
|
+
rb_define_const(mFiddle, "TYPE_SIZE_T", INT2NUM(TYPE_SIZE_T));
|
234
|
+
|
235
|
+
/* Document-const: TYPE_SSIZE_T
|
236
|
+
*
|
237
|
+
* C type - ssize_t
|
238
|
+
*/
|
239
|
+
rb_define_const(mFiddle, "TYPE_SSIZE_T", INT2NUM(TYPE_SSIZE_T));
|
240
|
+
|
241
|
+
/* Document-const: TYPE_PTRDIFF_T
|
242
|
+
*
|
243
|
+
* C type - ptrdiff_t
|
244
|
+
*/
|
245
|
+
rb_define_const(mFiddle, "TYPE_PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));
|
246
|
+
|
247
|
+
/* Document-const: TYPE_INTPTR_T
|
248
|
+
*
|
249
|
+
* C type - intptr_t
|
250
|
+
*/
|
251
|
+
rb_define_const(mFiddle, "TYPE_INTPTR_T", INT2NUM(TYPE_INTPTR_T));
|
252
|
+
|
253
|
+
/* Document-const: TYPE_UINTPTR_T
|
254
|
+
*
|
255
|
+
* C type - uintptr_t
|
256
|
+
*/
|
257
|
+
rb_define_const(mFiddle, "TYPE_UINTPTR_T", INT2NUM(TYPE_UINTPTR_T));
|
258
|
+
|
259
|
+
/* Document-const: ALIGN_VOIDP
|
260
|
+
*
|
261
|
+
* The alignment size of a void*
|
262
|
+
*/
|
263
|
+
rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
|
264
|
+
|
265
|
+
/* Document-const: ALIGN_CHAR
|
266
|
+
*
|
267
|
+
* The alignment size of a char
|
268
|
+
*/
|
269
|
+
rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR));
|
270
|
+
|
271
|
+
/* Document-const: ALIGN_SHORT
|
272
|
+
*
|
273
|
+
* The alignment size of a short
|
274
|
+
*/
|
275
|
+
rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
|
276
|
+
|
277
|
+
/* Document-const: ALIGN_INT
|
278
|
+
*
|
279
|
+
* The alignment size of an int
|
280
|
+
*/
|
281
|
+
rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT));
|
282
|
+
|
283
|
+
/* Document-const: ALIGN_LONG
|
284
|
+
*
|
285
|
+
* The alignment size of a long
|
286
|
+
*/
|
287
|
+
rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
|
288
|
+
|
289
|
+
#if HAVE_LONG_LONG
|
290
|
+
/* Document-const: ALIGN_LONG_LONG
|
291
|
+
*
|
292
|
+
* The alignment size of a long long
|
293
|
+
*/
|
294
|
+
rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG));
|
295
|
+
#endif
|
296
|
+
|
297
|
+
/* Document-const: ALIGN_FLOAT
|
298
|
+
*
|
299
|
+
* The alignment size of a float
|
300
|
+
*/
|
301
|
+
rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
|
302
|
+
|
303
|
+
/* Document-const: ALIGN_DOUBLE
|
304
|
+
*
|
305
|
+
* The alignment size of a double
|
306
|
+
*/
|
307
|
+
rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
|
308
|
+
|
309
|
+
/* Document-const: ALIGN_SIZE_T
|
310
|
+
*
|
311
|
+
* The alignment size of a size_t
|
312
|
+
*/
|
313
|
+
rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t)));
|
314
|
+
|
315
|
+
/* Document-const: ALIGN_SSIZE_T
|
316
|
+
*
|
317
|
+
* The alignment size of a ssize_t
|
318
|
+
*/
|
319
|
+
rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */
|
320
|
+
|
321
|
+
/* Document-const: ALIGN_PTRDIFF_T
|
322
|
+
*
|
323
|
+
* The alignment size of a ptrdiff_t
|
324
|
+
*/
|
325
|
+
rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t)));
|
326
|
+
|
327
|
+
/* Document-const: ALIGN_INTPTR_T
|
328
|
+
*
|
329
|
+
* The alignment size of a intptr_t
|
330
|
+
*/
|
331
|
+
rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t)));
|
332
|
+
|
333
|
+
/* Document-const: ALIGN_UINTPTR_T
|
334
|
+
*
|
335
|
+
* The alignment size of a uintptr_t
|
336
|
+
*/
|
337
|
+
rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t)));
|
338
|
+
|
339
|
+
/* Document-const: WINDOWS
|
340
|
+
*
|
341
|
+
* Returns a boolean regarding whether the host is WIN32
|
342
|
+
*/
|
343
|
+
#if defined(_WIN32)
|
344
|
+
rb_define_const(mFiddle, "WINDOWS", Qtrue);
|
345
|
+
#else
|
346
|
+
rb_define_const(mFiddle, "WINDOWS", Qfalse);
|
347
|
+
#endif
|
348
|
+
|
349
|
+
/* Document-const: SIZEOF_VOIDP
|
350
|
+
*
|
351
|
+
* size of a void*
|
352
|
+
*/
|
353
|
+
rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
|
354
|
+
|
355
|
+
/* Document-const: SIZEOF_CHAR
|
356
|
+
*
|
357
|
+
* size of a char
|
358
|
+
*/
|
359
|
+
rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char)));
|
360
|
+
|
361
|
+
/* Document-const: SIZEOF_SHORT
|
362
|
+
*
|
363
|
+
* size of a short
|
364
|
+
*/
|
365
|
+
rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
|
366
|
+
|
367
|
+
/* Document-const: SIZEOF_INT
|
368
|
+
*
|
369
|
+
* size of an int
|
370
|
+
*/
|
371
|
+
rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int)));
|
372
|
+
|
373
|
+
/* Document-const: SIZEOF_LONG
|
374
|
+
*
|
375
|
+
* size of a long
|
376
|
+
*/
|
377
|
+
rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long)));
|
378
|
+
|
379
|
+
#if HAVE_LONG_LONG
|
380
|
+
/* Document-const: SIZEOF_LONG_LONG
|
381
|
+
*
|
382
|
+
* size of a long long
|
383
|
+
*/
|
384
|
+
rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
|
385
|
+
#endif
|
386
|
+
|
387
|
+
/* Document-const: SIZEOF_FLOAT
|
388
|
+
*
|
389
|
+
* size of a float
|
390
|
+
*/
|
391
|
+
rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));
|
392
|
+
|
393
|
+
/* Document-const: SIZEOF_DOUBLE
|
394
|
+
*
|
395
|
+
* size of a double
|
396
|
+
*/
|
397
|
+
rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
|
398
|
+
|
399
|
+
/* Document-const: SIZEOF_SIZE_T
|
400
|
+
*
|
401
|
+
* size of a size_t
|
402
|
+
*/
|
403
|
+
rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t)));
|
404
|
+
|
405
|
+
/* Document-const: SIZEOF_SSIZE_T
|
406
|
+
*
|
407
|
+
* size of a ssize_t
|
408
|
+
*/
|
409
|
+
rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */
|
410
|
+
|
411
|
+
/* Document-const: SIZEOF_PTRDIFF_T
|
412
|
+
*
|
413
|
+
* size of a ptrdiff_t
|
414
|
+
*/
|
415
|
+
rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t)));
|
416
|
+
|
417
|
+
/* Document-const: SIZEOF_INTPTR_T
|
418
|
+
*
|
419
|
+
* size of a intptr_t
|
420
|
+
*/
|
421
|
+
rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t)));
|
422
|
+
|
423
|
+
/* Document-const: SIZEOF_UINTPTR_T
|
424
|
+
*
|
425
|
+
* size of a uintptr_t
|
426
|
+
*/
|
427
|
+
rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
|
428
|
+
|
429
|
+
/* Document-const: RUBY_FREE
|
430
|
+
*
|
431
|
+
* Address of the ruby_xfree() function
|
432
|
+
*/
|
433
|
+
rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree));
|
434
|
+
|
435
|
+
/* Document-const: BUILD_RUBY_PLATFORM
|
436
|
+
*
|
437
|
+
* Platform built against (i.e. "x86_64-linux", etc.)
|
438
|
+
*
|
439
|
+
* See also RUBY_PLATFORM
|
440
|
+
*/
|
441
|
+
rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));
|
442
|
+
|
443
|
+
rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
|
444
|
+
rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1);
|
445
|
+
rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1);
|
446
|
+
rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
|
447
|
+
rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);
|
448
|
+
|
449
|
+
Init_fiddle_function();
|
450
|
+
Init_fiddle_closure();
|
451
|
+
Init_fiddle_handle();
|
452
|
+
Init_fiddle_pointer();
|
453
|
+
}
|
454
|
+
/* vim: set noet sws=4 sw=4: */
|