fiddle 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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: */
|