rubysl-dl 0.0.1 → 1.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/.gitignore +0 -1
- data/.travis.yml +8 -0
- data/README.md +2 -2
- data/Rakefile +0 -1
- data/ext/rubysl/dl/depend +46 -0
- data/ext/rubysl/dl/dl.c +742 -0
- data/ext/rubysl/dl/dl.def +59 -0
- data/ext/rubysl/dl/dl.h +313 -0
- data/ext/rubysl/dl/extconf.rb +193 -0
- data/ext/rubysl/dl/h2rb +500 -0
- data/ext/rubysl/dl/handle.c +215 -0
- data/ext/rubysl/dl/install.rb +49 -0
- data/ext/rubysl/dl/lib/dl/import.rb +225 -0
- data/ext/rubysl/dl/lib/dl/struct.rb +149 -0
- data/ext/rubysl/dl/lib/dl/types.rb +245 -0
- data/ext/rubysl/dl/lib/dl/win32.rb +25 -0
- data/ext/rubysl/dl/mkcall.rb +69 -0
- data/ext/rubysl/dl/mkcallback.rb +63 -0
- data/ext/rubysl/dl/mkcbtable.rb +25 -0
- data/ext/rubysl/dl/ptr.c +1062 -0
- data/ext/rubysl/dl/sample/c++sample.C +35 -0
- data/ext/rubysl/dl/sample/c++sample.rb +60 -0
- data/ext/rubysl/dl/sample/drives.rb +70 -0
- data/ext/rubysl/dl/sample/getch.rb +5 -0
- data/ext/rubysl/dl/sample/libc.rb +69 -0
- data/ext/rubysl/dl/sample/msgbox.rb +19 -0
- data/ext/rubysl/dl/sample/msgbox2.rb +18 -0
- data/ext/rubysl/dl/sample/stream.rb +87 -0
- data/ext/rubysl/dl/sym.c +993 -0
- data/ext/rubysl/dl/test/libtest.def +28 -0
- data/ext/rubysl/dl/test/test.c +247 -0
- data/ext/rubysl/dl/test/test.rb +306 -0
- data/ext/rubysl/dl/type.rb +115 -0
- data/lib/dl.rb +1 -0
- data/lib/rubysl/dl.rb +2 -0
- data/lib/rubysl/dl/version.rb +5 -0
- data/rubysl-dl.gemspec +20 -18
- metadata +109 -87
- data/lib/rubysl-dl.rb +0 -7
- data/lib/rubysl-dl/version.rb +0 -5
@@ -0,0 +1,35 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
|
3
|
+
class Person {
|
4
|
+
private:
|
5
|
+
const char *name;
|
6
|
+
int age;
|
7
|
+
|
8
|
+
public:
|
9
|
+
Person(const char *name, int age);
|
10
|
+
const char * get_name();
|
11
|
+
int get_age();
|
12
|
+
void set_age(int i);
|
13
|
+
};
|
14
|
+
|
15
|
+
Person::Person(const char *name, int age)
|
16
|
+
: name(name), age(age)
|
17
|
+
{
|
18
|
+
/* empty */
|
19
|
+
}
|
20
|
+
|
21
|
+
const char *
|
22
|
+
Person::get_name()
|
23
|
+
{
|
24
|
+
return name;
|
25
|
+
}
|
26
|
+
|
27
|
+
int
|
28
|
+
Person::get_age(){
|
29
|
+
return age;
|
30
|
+
}
|
31
|
+
|
32
|
+
void
|
33
|
+
Person::set_age(int i){
|
34
|
+
age = i;
|
35
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
=begin
|
2
|
+
This script shows how to deal with C++ classes using Ruby/DL.
|
3
|
+
You must build a dynamic loadable library using "c++sample.C"
|
4
|
+
to run this script as follows:
|
5
|
+
$ g++ -o libsample.so -shared c++sample.C
|
6
|
+
=end
|
7
|
+
|
8
|
+
require 'dl'
|
9
|
+
require 'dl/import'
|
10
|
+
require 'dl/struct'
|
11
|
+
|
12
|
+
# Give a name of dynamic loadable library
|
13
|
+
LIBNAME = ARGV[0] || "libsample.so"
|
14
|
+
|
15
|
+
class Person
|
16
|
+
module Core
|
17
|
+
extend DL::Importable
|
18
|
+
|
19
|
+
dlload LIBNAME
|
20
|
+
|
21
|
+
# mangled symbol names
|
22
|
+
extern "void __6PersonPCci(void *, const char *, int)"
|
23
|
+
extern "const char *get_name__6Person(void *)"
|
24
|
+
extern "int get_age__6Person(void *)"
|
25
|
+
extern "void set_age__6Personi(void *, int)"
|
26
|
+
|
27
|
+
Data = struct [
|
28
|
+
"char *name",
|
29
|
+
"int age",
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(name, age)
|
34
|
+
@ptr = Core::Data.alloc
|
35
|
+
Core::__6PersonPCci(@ptr, name, age)
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_name()
|
39
|
+
str = Core::get_name__6Person(@ptr)
|
40
|
+
if( str )
|
41
|
+
str.to_s
|
42
|
+
else
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_age()
|
48
|
+
Core::get_age__6Person(@ptr)
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_age(age)
|
52
|
+
Core::set_age__6Personi(@ptr, age)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
obj = Person.new("ttate", 1)
|
57
|
+
p obj.get_name()
|
58
|
+
p obj.get_age()
|
59
|
+
obj.set_age(10)
|
60
|
+
p obj.get_age()
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# drives.rb -- find existing drives and show the drive type.
|
3
|
+
|
4
|
+
require 'dl'
|
5
|
+
require 'dl/import'
|
6
|
+
|
7
|
+
module Kernel32
|
8
|
+
extend DL::Importable
|
9
|
+
|
10
|
+
dlload "kernel32"
|
11
|
+
|
12
|
+
extern "long GetLogicalDrives()"
|
13
|
+
extern "int GetDriveType(char*)"
|
14
|
+
extern "long GetDiskFreeSpace(char*, long ref, long ref, long ref, long ref)"
|
15
|
+
end
|
16
|
+
|
17
|
+
include Kernel32
|
18
|
+
|
19
|
+
buff = Kernel32.getLogicalDrives()
|
20
|
+
|
21
|
+
i = 0
|
22
|
+
ds = []
|
23
|
+
while( i < 26 )
|
24
|
+
mask = (1 << i)
|
25
|
+
if( buff & mask > 0 )
|
26
|
+
ds.push((65+i).chr)
|
27
|
+
end
|
28
|
+
i += 1
|
29
|
+
end
|
30
|
+
|
31
|
+
=begin
|
32
|
+
From the cygwin's /usr/include/w32api/winbase.h:
|
33
|
+
#define DRIVE_UNKNOWN 0
|
34
|
+
#define DRIVE_NO_ROOT_DIR 1
|
35
|
+
#define DRIVE_REMOVABLE 2
|
36
|
+
#define DRIVE_FIXED 3
|
37
|
+
#define DRIVE_REMOTE 4
|
38
|
+
#define DRIVE_CDROM 5
|
39
|
+
#define DRIVE_RAMDISK 6
|
40
|
+
=end
|
41
|
+
|
42
|
+
types = [
|
43
|
+
"unknown",
|
44
|
+
"no root dir",
|
45
|
+
"Removable",
|
46
|
+
"Fixed",
|
47
|
+
"Remote",
|
48
|
+
"CDROM",
|
49
|
+
"RAM",
|
50
|
+
]
|
51
|
+
print("Drive : Type (Free Space/Available Space)\n")
|
52
|
+
ds.each{|d|
|
53
|
+
t = Kernel32.getDriveType(d + ":\\")
|
54
|
+
Kernel32.getDiskFreeSpace(d + ":\\", 0, 0, 0, 0)
|
55
|
+
_,sec_per_clus,byte_per_sec,free_clus,total_clus = Kernel32._args_
|
56
|
+
fbytes = sec_per_clus * byte_per_sec * free_clus
|
57
|
+
tbytes = sec_per_clus * byte_per_sec * total_clus
|
58
|
+
unit = "B"
|
59
|
+
if( fbytes > 1024 && tbytes > 1024 )
|
60
|
+
fbytes = fbytes / 1024
|
61
|
+
tbytes = tbytes / 1024
|
62
|
+
unit = "K"
|
63
|
+
end
|
64
|
+
if( fbytes > 1024 && tbytes > 1024 )
|
65
|
+
fbytes = fbytes / 1024
|
66
|
+
tbytes = tbytes / 1024
|
67
|
+
unit = "M"
|
68
|
+
end
|
69
|
+
print("#{d} : #{types[t]} (#{fbytes} #{unit}/#{tbytes} #{unit})\n")
|
70
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "dl/import"
|
2
|
+
require "dl/struct"
|
3
|
+
|
4
|
+
module LIBC
|
5
|
+
extend DL::Importable
|
6
|
+
|
7
|
+
begin
|
8
|
+
dlload "libc.so.6"
|
9
|
+
rescue
|
10
|
+
dlload "libc.so.5"
|
11
|
+
end
|
12
|
+
|
13
|
+
extern "int atoi(char*)"
|
14
|
+
extern "ibool isdigit(int)"
|
15
|
+
extern "int gettimeofday(struct timeval *, struct timezone *)"
|
16
|
+
extern "char* strcat(char*, char*)"
|
17
|
+
extern "FILE* fopen(char*, char*)"
|
18
|
+
extern "int fclose(FILE*)"
|
19
|
+
extern "int fgetc(FILE*)"
|
20
|
+
extern "int strlen(char*)"
|
21
|
+
extern "void qsort(void*, int, int, void*)"
|
22
|
+
|
23
|
+
def str_qsort(ary, comp)
|
24
|
+
len = ary.length
|
25
|
+
r,rs = qsort(ary, len, DL.sizeof('P'), comp)
|
26
|
+
return rs[0].to_a('S', len)
|
27
|
+
end
|
28
|
+
|
29
|
+
Timeval = struct [
|
30
|
+
"long tv_sec",
|
31
|
+
"long tv_usec",
|
32
|
+
]
|
33
|
+
|
34
|
+
Timezone = struct [
|
35
|
+
"int tz_minuteswest",
|
36
|
+
"int tz_dsttime",
|
37
|
+
]
|
38
|
+
|
39
|
+
def my_compare(ptr1, ptr2)
|
40
|
+
ptr1.ptr.to_s <=> ptr2.ptr.to_s
|
41
|
+
end
|
42
|
+
COMPARE = callback("int my_compare(char**, char**)")
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
$cb1 = DL.callback('IPP'){|ptr1, ptr2|
|
47
|
+
str1 = ptr1.ptr.to_s
|
48
|
+
str2 = ptr2.ptr.to_s
|
49
|
+
str1 <=> str2
|
50
|
+
}
|
51
|
+
|
52
|
+
p LIBC.atoi("10")
|
53
|
+
|
54
|
+
p LIBC.isdigit(?1)
|
55
|
+
|
56
|
+
p LIBC.isdigit(?a)
|
57
|
+
|
58
|
+
p LIBC.strcat("a", "b")
|
59
|
+
|
60
|
+
ary = ["a","c","b"]
|
61
|
+
ptr = ary.to_ptr
|
62
|
+
LIBC.qsort(ptr, ary.length, DL.sizeof('P'), LIBC::COMPARE)
|
63
|
+
p ptr.to_a('S', ary.length)
|
64
|
+
|
65
|
+
tv = LIBC::Timeval.malloc
|
66
|
+
tz = LIBC::Timezone.malloc
|
67
|
+
LIBC.gettimeofday(tv, tz)
|
68
|
+
|
69
|
+
p Time.at(tv.tv_sec)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# This script works on Windows.
|
2
|
+
|
3
|
+
require 'dl'
|
4
|
+
|
5
|
+
User32 = DL.dlopen("user32")
|
6
|
+
Kernel32 = DL.dlopen("kernel32")
|
7
|
+
|
8
|
+
MB_OK = 0
|
9
|
+
MB_OKCANCEL = 1
|
10
|
+
|
11
|
+
message_box = User32['MessageBoxA', 'ILSSI']
|
12
|
+
r,rs = message_box.call(0, 'ok?', 'error', MB_OKCANCEL)
|
13
|
+
|
14
|
+
case r
|
15
|
+
when 1
|
16
|
+
print("OK!\n")
|
17
|
+
when 2
|
18
|
+
print("Cancel!\n")
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# This script works on Windows.
|
2
|
+
|
3
|
+
require 'dl/win32'
|
4
|
+
|
5
|
+
MB_OK = 0
|
6
|
+
MB_OKCANCEL = 1
|
7
|
+
|
8
|
+
message_box = Win32API.new("user32",'MessageBoxA', 'ISSI', 'I')
|
9
|
+
r = message_box.call(0, 'ok?', 'error', MB_OKCANCEL)
|
10
|
+
|
11
|
+
case r
|
12
|
+
when 1
|
13
|
+
print("OK!\n")
|
14
|
+
when 2
|
15
|
+
print("Cancel!\n")
|
16
|
+
else
|
17
|
+
p r
|
18
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# Display a file name and stream names of a file with those size.
|
3
|
+
|
4
|
+
require 'dl'
|
5
|
+
require 'dl/import'
|
6
|
+
|
7
|
+
module NTFS
|
8
|
+
extend DL::Importable
|
9
|
+
|
10
|
+
dlload "kernel32.dll"
|
11
|
+
|
12
|
+
OPEN_EXISTING = 3
|
13
|
+
GENERIC_READ = 0x80000000
|
14
|
+
BACKUP_DATA = 0x00000001
|
15
|
+
BACKUP_ALTERNATE_DATA = 0x00000004
|
16
|
+
FILE_SHARE_READ = 0x00000001
|
17
|
+
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
|
18
|
+
|
19
|
+
typealias "LPSECURITY_ATTRIBUTES", "void*"
|
20
|
+
|
21
|
+
extern "BOOL BackupRead(HANDLE, PBYTE, DWORD, PDWORD, BOOL, BOOL, PVOID)"
|
22
|
+
extern "BOOL BackupSeek(HANDLE, DWORD, DWORD, PDWORD, PDWORD, PVOID)"
|
23
|
+
extern "BOOL CloseHandle(HANDLE)"
|
24
|
+
extern "HANDLE CreateFile(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES,
|
25
|
+
DWORD, DWORD, HANDLE)"
|
26
|
+
|
27
|
+
module_function
|
28
|
+
|
29
|
+
def streams(filename)
|
30
|
+
status = []
|
31
|
+
h = createFile(filename,GENERIC_READ,FILE_SHARE_READ,nil,
|
32
|
+
OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0)
|
33
|
+
if( h != 0 )
|
34
|
+
begin
|
35
|
+
# allocate the memory for backup data used in backupRead().
|
36
|
+
data = DL.malloc(DL.sizeof("L5"))
|
37
|
+
data.struct!("LLLLL", :id, :attrs, :size_low, :size_high, :name_size)
|
38
|
+
|
39
|
+
# allocate memories for references to long values used in backupRead().
|
40
|
+
context = DL.malloc(DL.sizeof("L"))
|
41
|
+
lval = DL.malloc(DL.sizeof("L"))
|
42
|
+
|
43
|
+
while( backupRead(h, data, data.size, lval, false, false, context) )
|
44
|
+
size = data[:size_low] + (data[:size_high] << (DL.sizeof("I") * 8))
|
45
|
+
case data[:id]
|
46
|
+
when BACKUP_ALTERNATE_DATA
|
47
|
+
stream_name = DL.malloc(data[:name_size])
|
48
|
+
backupRead(h, stream_name, stream_name.size,
|
49
|
+
lval, false, false, context)
|
50
|
+
name = stream_name[0, stream_name.size]
|
51
|
+
name.tr!("\000","")
|
52
|
+
if( name =~ /^:(.*?):.*$/ )
|
53
|
+
status.push([$1,size])
|
54
|
+
end
|
55
|
+
when BACKUP_DATA
|
56
|
+
status.push([nil,size])
|
57
|
+
else
|
58
|
+
raise(RuntimeError, "unknown data type #{data[:id]}.")
|
59
|
+
end
|
60
|
+
l1 = DL.malloc(DL.sizeof("L"))
|
61
|
+
l2 = DL.malloc(DL.sizeof("L"))
|
62
|
+
if( !backupSeek(h, data[:size_low], data[:size_high], l1, l2, context) )
|
63
|
+
break
|
64
|
+
end
|
65
|
+
end
|
66
|
+
ensure
|
67
|
+
backupRead(h, nil, 0, lval, true, false, context)
|
68
|
+
closeHandle(h)
|
69
|
+
end
|
70
|
+
return status
|
71
|
+
else
|
72
|
+
raise(RuntimeError, "can't open #{filename}.\n")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
ARGV.each{|filename|
|
78
|
+
if( File.exist?(filename) )
|
79
|
+
NTFS.streams(filename).each{|name,size|
|
80
|
+
if( name )
|
81
|
+
print("#{filename}:#{name}\t#{size}bytes\n")
|
82
|
+
else
|
83
|
+
print("#{filename}\t#{size}bytes\n")
|
84
|
+
end
|
85
|
+
}
|
86
|
+
end
|
87
|
+
}
|
data/ext/rubysl/dl/sym.c
ADDED
@@ -0,0 +1,993 @@
|
|
1
|
+
/* -*- C -*-
|
2
|
+
* $Id: sym.c 18479 2008-08-11 00:37:21Z shyouhei $
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include <ruby.h>
|
6
|
+
#include <errno.h>
|
7
|
+
#include "dl.h"
|
8
|
+
|
9
|
+
VALUE rb_cDLSymbol;
|
10
|
+
|
11
|
+
static const char *
|
12
|
+
char2type(int ch)
|
13
|
+
{
|
14
|
+
switch (ch) {
|
15
|
+
case '0':
|
16
|
+
return "void";
|
17
|
+
case 'P':
|
18
|
+
return "void *";
|
19
|
+
case 'p':
|
20
|
+
return "void *";
|
21
|
+
case 'C':
|
22
|
+
return "char";
|
23
|
+
case 'c':
|
24
|
+
return "char *";
|
25
|
+
case 'H':
|
26
|
+
return "short";
|
27
|
+
case 'h':
|
28
|
+
return "short *";
|
29
|
+
case 'I':
|
30
|
+
return "int";
|
31
|
+
case 'i':
|
32
|
+
return "int *";
|
33
|
+
case 'L':
|
34
|
+
return "long";
|
35
|
+
case 'l':
|
36
|
+
return "long *";
|
37
|
+
case 'F':
|
38
|
+
return "double";
|
39
|
+
case 'f':
|
40
|
+
return "double *";
|
41
|
+
case 'D':
|
42
|
+
return "double";
|
43
|
+
case 'd':
|
44
|
+
return "double *";
|
45
|
+
case 'S':
|
46
|
+
return "const char *";
|
47
|
+
case 's':
|
48
|
+
return "char *";
|
49
|
+
case 'A':
|
50
|
+
return "[]";
|
51
|
+
case 'a':
|
52
|
+
return "[]"; /* ?? */
|
53
|
+
}
|
54
|
+
return NULL;
|
55
|
+
}
|
56
|
+
|
57
|
+
void
|
58
|
+
dlsym_free(struct sym_data *data)
|
59
|
+
{
|
60
|
+
if( data->name ){
|
61
|
+
DEBUG_CODE({
|
62
|
+
printf("dlsym_free(): free(data->name:%s)\n",data->name);
|
63
|
+
});
|
64
|
+
free(data->name);
|
65
|
+
}
|
66
|
+
if( data->type ){
|
67
|
+
DEBUG_CODE({
|
68
|
+
printf("dlsym_free(): free(data->type:%s)\n",data->type);
|
69
|
+
});
|
70
|
+
free(data->type);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
VALUE
|
75
|
+
rb_dlsym_new(void (*func)(), const char *name, const char *type)
|
76
|
+
{
|
77
|
+
VALUE val;
|
78
|
+
struct sym_data *data;
|
79
|
+
const char *ptype;
|
80
|
+
|
81
|
+
rb_secure(4);
|
82
|
+
if( !type || !type[0] ){
|
83
|
+
return rb_dlptr_new((void*)func, 0, 0);
|
84
|
+
}
|
85
|
+
|
86
|
+
for( ptype = type; *ptype; ptype ++ ){
|
87
|
+
if( ! char2type(*ptype) ){
|
88
|
+
rb_raise(rb_eDLTypeError, "unknown type specifier '%c'", *ptype);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
if( func ){
|
93
|
+
val = Data_Make_Struct(rb_cDLSymbol, struct sym_data, 0, dlsym_free, data);
|
94
|
+
data->func = func;
|
95
|
+
data->name = name ? strdup(name) : NULL;
|
96
|
+
data->type = type ? strdup(type) : NULL;
|
97
|
+
data->len = type ? strlen(type) : 0;
|
98
|
+
#if !(defined(DLSTACK))
|
99
|
+
if( data->len - 1 > MAX_ARG ){
|
100
|
+
rb_raise(rb_eDLError, "maximum number of arguments is %d.", MAX_ARG);
|
101
|
+
}
|
102
|
+
#endif
|
103
|
+
}
|
104
|
+
else{
|
105
|
+
val = Qnil;
|
106
|
+
}
|
107
|
+
|
108
|
+
return val;
|
109
|
+
}
|
110
|
+
|
111
|
+
freefunc_t
|
112
|
+
rb_dlsym2csym(VALUE val)
|
113
|
+
{
|
114
|
+
struct sym_data *data;
|
115
|
+
freefunc_t func;
|
116
|
+
|
117
|
+
if( rb_obj_is_kind_of(val, rb_cDLSymbol) ){
|
118
|
+
Data_Get_Struct(val, struct sym_data, data);
|
119
|
+
func = data->func;
|
120
|
+
}
|
121
|
+
else if( val == Qnil ){
|
122
|
+
func = NULL;
|
123
|
+
}
|
124
|
+
else{
|
125
|
+
rb_raise(rb_eTypeError, "DL::Symbol was expected");
|
126
|
+
}
|
127
|
+
|
128
|
+
return func;
|
129
|
+
}
|
130
|
+
|
131
|
+
VALUE
|
132
|
+
rb_dlsym_s_allocate(VALUE klass)
|
133
|
+
{
|
134
|
+
VALUE obj;
|
135
|
+
struct sym_data *data;
|
136
|
+
|
137
|
+
obj = Data_Make_Struct(klass, struct sym_data, 0, dlsym_free, data);
|
138
|
+
data->func = 0;
|
139
|
+
data->name = 0;
|
140
|
+
data->type = 0;
|
141
|
+
data->len = 0;
|
142
|
+
|
143
|
+
return obj;
|
144
|
+
}
|
145
|
+
|
146
|
+
VALUE
|
147
|
+
rb_dlsym_initialize(int argc, VALUE argv[], VALUE self)
|
148
|
+
{
|
149
|
+
VALUE addr, name, type;
|
150
|
+
struct sym_data *data;
|
151
|
+
void *saddr;
|
152
|
+
const char *sname, *stype;
|
153
|
+
|
154
|
+
rb_scan_args(argc, argv, "12", &addr, &name, &type);
|
155
|
+
|
156
|
+
saddr = (void*)(DLNUM2LONG(rb_Integer(addr)));
|
157
|
+
if (!NIL_P(name)) StringValue(name);
|
158
|
+
stype = NIL_P(type) ? NULL : StringValuePtr(type);
|
159
|
+
sname = NIL_P(name) ? NULL : RSTRING(name)->ptr;
|
160
|
+
|
161
|
+
if( saddr ){
|
162
|
+
Data_Get_Struct(self, struct sym_data, data);
|
163
|
+
if( data->name ) free(data->name);
|
164
|
+
if( data->type ) free(data->type);
|
165
|
+
data->func = saddr;
|
166
|
+
data->name = sname ? strdup(sname) : 0;
|
167
|
+
data->type = stype ? strdup(stype) : 0;
|
168
|
+
data->len = stype ? strlen(stype) : 0;
|
169
|
+
}
|
170
|
+
|
171
|
+
return Qnil;
|
172
|
+
}
|
173
|
+
|
174
|
+
VALUE
|
175
|
+
rb_s_dlsym_char2type(VALUE self, VALUE ch)
|
176
|
+
{
|
177
|
+
const char *type;
|
178
|
+
|
179
|
+
type = char2type(StringValuePtr(ch)[0]);
|
180
|
+
|
181
|
+
if (type == NULL)
|
182
|
+
return Qnil;
|
183
|
+
else
|
184
|
+
return rb_str_new2(type);
|
185
|
+
}
|
186
|
+
|
187
|
+
VALUE
|
188
|
+
rb_dlsym_name(VALUE self)
|
189
|
+
{
|
190
|
+
struct sym_data *sym;
|
191
|
+
|
192
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
193
|
+
return sym->name ? rb_tainted_str_new2(sym->name) : Qnil;
|
194
|
+
}
|
195
|
+
|
196
|
+
VALUE
|
197
|
+
rb_dlsym_proto(VALUE self)
|
198
|
+
{
|
199
|
+
struct sym_data *sym;
|
200
|
+
|
201
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
202
|
+
return sym->type ? rb_tainted_str_new2(sym->type) : Qnil;
|
203
|
+
}
|
204
|
+
|
205
|
+
VALUE
|
206
|
+
rb_dlsym_cproto(VALUE self)
|
207
|
+
{
|
208
|
+
struct sym_data *sym;
|
209
|
+
const char *ptype, *typestr;
|
210
|
+
size_t len;
|
211
|
+
VALUE val;
|
212
|
+
|
213
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
214
|
+
|
215
|
+
ptype = sym->type;
|
216
|
+
|
217
|
+
if( ptype ){
|
218
|
+
typestr = char2type(*ptype++);
|
219
|
+
len = strlen(typestr);
|
220
|
+
|
221
|
+
val = rb_tainted_str_new(typestr, len);
|
222
|
+
if (typestr[len - 1] != '*')
|
223
|
+
rb_str_cat(val, " ", 1);
|
224
|
+
|
225
|
+
if( sym->name ){
|
226
|
+
rb_str_cat2(val, sym->name);
|
227
|
+
}
|
228
|
+
else{
|
229
|
+
rb_str_cat2(val, "(null)");
|
230
|
+
}
|
231
|
+
rb_str_cat(val, "(", 1);
|
232
|
+
|
233
|
+
while (*ptype) {
|
234
|
+
const char *ty = char2type(*ptype++);
|
235
|
+
rb_str_cat2(val, ty);
|
236
|
+
if (*ptype)
|
237
|
+
rb_str_cat(val, ", ", 2);
|
238
|
+
}
|
239
|
+
|
240
|
+
rb_str_cat(val, ");", 2);
|
241
|
+
}
|
242
|
+
else{
|
243
|
+
val = rb_tainted_str_new2("void (");
|
244
|
+
if( sym->name ){
|
245
|
+
rb_str_cat2(val, sym->name);
|
246
|
+
}
|
247
|
+
else{
|
248
|
+
rb_str_cat2(val, "(null)");
|
249
|
+
}
|
250
|
+
rb_str_cat2(val, ")()");
|
251
|
+
}
|
252
|
+
|
253
|
+
return val;
|
254
|
+
}
|
255
|
+
|
256
|
+
VALUE
|
257
|
+
rb_dlsym_inspect(VALUE self)
|
258
|
+
{
|
259
|
+
VALUE proto;
|
260
|
+
VALUE val;
|
261
|
+
char *str;
|
262
|
+
int str_size;
|
263
|
+
struct sym_data *sym;
|
264
|
+
|
265
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
266
|
+
proto = rb_dlsym_cproto(self);
|
267
|
+
|
268
|
+
str_size = RSTRING(proto)->len + 100;
|
269
|
+
str = dlmalloc(str_size);
|
270
|
+
snprintf(str, str_size - 1,
|
271
|
+
"#<DL::Symbol:0x%lx func=0x%lx '%s'>",
|
272
|
+
(long unsigned)sym, (long unsigned)sym->func, RSTRING(proto)->ptr);
|
273
|
+
val = rb_tainted_str_new2(str);
|
274
|
+
dlfree(str);
|
275
|
+
|
276
|
+
return val;
|
277
|
+
}
|
278
|
+
|
279
|
+
static int
|
280
|
+
stack_size(struct sym_data *sym)
|
281
|
+
{
|
282
|
+
int i;
|
283
|
+
int size;
|
284
|
+
|
285
|
+
size = 0;
|
286
|
+
for( i=1; i < sym->len; i++ ){
|
287
|
+
switch(sym->type[i]){
|
288
|
+
case 'C':
|
289
|
+
case 'H':
|
290
|
+
case 'I':
|
291
|
+
case 'L':
|
292
|
+
size += sizeof(long);
|
293
|
+
break;
|
294
|
+
case 'F':
|
295
|
+
size += sizeof(float);
|
296
|
+
break;
|
297
|
+
case 'D':
|
298
|
+
size += sizeof(double);
|
299
|
+
break;
|
300
|
+
case 'c':
|
301
|
+
case 'h':
|
302
|
+
case 'i':
|
303
|
+
case 'l':
|
304
|
+
case 'f':
|
305
|
+
case 'd':
|
306
|
+
case 'p':
|
307
|
+
case 'P':
|
308
|
+
case 's':
|
309
|
+
case 'S':
|
310
|
+
case 'a':
|
311
|
+
case 'A':
|
312
|
+
size += sizeof(void*);
|
313
|
+
break;
|
314
|
+
default:
|
315
|
+
return -(sym->type[i]);
|
316
|
+
}
|
317
|
+
}
|
318
|
+
return size;
|
319
|
+
}
|
320
|
+
|
321
|
+
static ID rb_dl_id_DLErrno;
|
322
|
+
|
323
|
+
static VALUE
|
324
|
+
rb_dl_get_last_error(VALUE self)
|
325
|
+
{
|
326
|
+
return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLErrno);
|
327
|
+
}
|
328
|
+
|
329
|
+
static VALUE
|
330
|
+
rb_dl_set_last_error(VALUE self, VALUE val)
|
331
|
+
{
|
332
|
+
errno = NUM2INT(val);
|
333
|
+
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, val);
|
334
|
+
return Qnil;
|
335
|
+
}
|
336
|
+
|
337
|
+
#ifdef HAVE_WINDOWS_H
|
338
|
+
#include <windows.h>
|
339
|
+
static ID rb_dl_id_DLW32Error;
|
340
|
+
|
341
|
+
static VALUE
|
342
|
+
rb_dl_win32_get_last_error(VALUE self)
|
343
|
+
{
|
344
|
+
return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLW32Error);
|
345
|
+
}
|
346
|
+
|
347
|
+
static VALUE
|
348
|
+
rb_dl_win32_set_last_error(VALUE self, VALUE val)
|
349
|
+
{
|
350
|
+
SetLastError(NUM2INT(val));
|
351
|
+
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, val);
|
352
|
+
return Qnil;
|
353
|
+
}
|
354
|
+
#endif
|
355
|
+
|
356
|
+
#ifdef DLSTACK_GUARD
|
357
|
+
# ifdef __MSVC_RUNTIME_CHECKS
|
358
|
+
# pragma runtime_checks("s", off)
|
359
|
+
# endif
|
360
|
+
# if _MSC_VER >= 1300
|
361
|
+
__declspec(noinline)
|
362
|
+
# endif
|
363
|
+
static int
|
364
|
+
rb_dlsym_guardcall(char type, ANY_TYPE *ret, long *stack, void *func)
|
365
|
+
{
|
366
|
+
char *volatile guard = ALLOCA_N(char, 1); /* guard stack pointer */
|
367
|
+
switch(type){
|
368
|
+
case '0':
|
369
|
+
{
|
370
|
+
void (*f)(DLSTACK_PROTO) = func;
|
371
|
+
f(DLSTACK_ARGS);
|
372
|
+
}
|
373
|
+
break;
|
374
|
+
case 'P':
|
375
|
+
case 'p':
|
376
|
+
{
|
377
|
+
void * (*f)(DLSTACK_PROTO) = func;
|
378
|
+
ret->p = f(DLSTACK_ARGS);
|
379
|
+
}
|
380
|
+
break;
|
381
|
+
case 'C':
|
382
|
+
case 'c':
|
383
|
+
{
|
384
|
+
char (*f)(DLSTACK_PROTO) = func;
|
385
|
+
ret->c = f(DLSTACK_ARGS);
|
386
|
+
}
|
387
|
+
break;
|
388
|
+
case 'H':
|
389
|
+
case 'h':
|
390
|
+
{
|
391
|
+
short (*f)(DLSTACK_PROTO) = func;
|
392
|
+
ret->h = f(DLSTACK_ARGS);
|
393
|
+
}
|
394
|
+
break;
|
395
|
+
case 'I':
|
396
|
+
case 'i':
|
397
|
+
{
|
398
|
+
int (*f)(DLSTACK_PROTO) = func;
|
399
|
+
ret->i = f(DLSTACK_ARGS);
|
400
|
+
}
|
401
|
+
break;
|
402
|
+
case 'L':
|
403
|
+
case 'l':
|
404
|
+
{
|
405
|
+
long (*f)(DLSTACK_PROTO) = func;
|
406
|
+
ret->l = f(DLSTACK_ARGS);
|
407
|
+
}
|
408
|
+
break;
|
409
|
+
case 'F':
|
410
|
+
case 'f':
|
411
|
+
{
|
412
|
+
float (*f)(DLSTACK_PROTO) = func;
|
413
|
+
ret->f = f(DLSTACK_ARGS);
|
414
|
+
}
|
415
|
+
break;
|
416
|
+
case 'D':
|
417
|
+
case 'd':
|
418
|
+
{
|
419
|
+
double (*f)(DLSTACK_PROTO) = func;
|
420
|
+
ret->d = f(DLSTACK_ARGS);
|
421
|
+
}
|
422
|
+
break;
|
423
|
+
case 'S':
|
424
|
+
case 's':
|
425
|
+
{
|
426
|
+
char * (*f)(DLSTACK_PROTO) = func;
|
427
|
+
ret->s = f(DLSTACK_ARGS);
|
428
|
+
}
|
429
|
+
break;
|
430
|
+
default:
|
431
|
+
return 0;
|
432
|
+
}
|
433
|
+
return 1;
|
434
|
+
}
|
435
|
+
# ifdef __MSVC_RUNTIME_CHECKS
|
436
|
+
# pragma runtime_checks("s", restore)
|
437
|
+
# endif
|
438
|
+
#endif /* defined(DLSTACK_GUARD) */
|
439
|
+
|
440
|
+
VALUE
|
441
|
+
rb_dlsym_call(int argc, VALUE argv[], VALUE self)
|
442
|
+
{
|
443
|
+
struct sym_data *sym;
|
444
|
+
ANY_TYPE *args;
|
445
|
+
ANY_TYPE *dargs;
|
446
|
+
ANY_TYPE ret;
|
447
|
+
int *dtypes;
|
448
|
+
VALUE val;
|
449
|
+
VALUE dvals;
|
450
|
+
int i;
|
451
|
+
long ftype;
|
452
|
+
void *func;
|
453
|
+
|
454
|
+
rb_secure_update(self);
|
455
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
456
|
+
DEBUG_CODE({
|
457
|
+
printf("rb_dlsym_call(): type = '%s', func = 0x%x\n", sym->type, sym->func);
|
458
|
+
});
|
459
|
+
if( (sym->len - 1) != argc ){
|
460
|
+
rb_raise(rb_eArgError, "%d arguments are needed", sym->len - 1);
|
461
|
+
}
|
462
|
+
|
463
|
+
ftype = 0;
|
464
|
+
dvals = Qnil;
|
465
|
+
|
466
|
+
args = ALLOC_N(ANY_TYPE, sym->len - 1);
|
467
|
+
dargs = ALLOC_N(ANY_TYPE, sym->len - 1);
|
468
|
+
dtypes = ALLOC_N(int, sym->len - 1);
|
469
|
+
#define FREE_ARGS {xfree(args); xfree(dargs); xfree(dtypes);}
|
470
|
+
|
471
|
+
for( i = sym->len - 2; i >= 0; i-- ){
|
472
|
+
dtypes[i] = 0;
|
473
|
+
|
474
|
+
switch( sym->type[i+1] ){
|
475
|
+
case 'p':
|
476
|
+
dtypes[i] = 'p';
|
477
|
+
case 'P':
|
478
|
+
{
|
479
|
+
struct ptr_data *data;
|
480
|
+
VALUE pval;
|
481
|
+
|
482
|
+
if( argv[i] == Qnil ){
|
483
|
+
ANY2P(args[i]) = DLVOIDP(0);
|
484
|
+
}
|
485
|
+
else{
|
486
|
+
if( rb_obj_is_kind_of(argv[i], rb_cDLPtrData) ){
|
487
|
+
pval = argv[i];
|
488
|
+
}
|
489
|
+
else{
|
490
|
+
pval = rb_funcall(argv[i], rb_intern("to_ptr"), 0);
|
491
|
+
if( !rb_obj_is_kind_of(pval, rb_cDLPtrData) ){
|
492
|
+
rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i);
|
493
|
+
}
|
494
|
+
}
|
495
|
+
rb_check_safe_obj(pval);
|
496
|
+
Data_Get_Struct(pval, struct ptr_data, data);
|
497
|
+
ANY2P(args[i]) = DLVOIDP(data->ptr);
|
498
|
+
}
|
499
|
+
}
|
500
|
+
PUSH_P(ftype);
|
501
|
+
break;
|
502
|
+
case 'a':
|
503
|
+
dtypes[i] = 'a';
|
504
|
+
case 'A':
|
505
|
+
if( argv[i] == Qnil ){
|
506
|
+
ANY2P(args[i]) = DLVOIDP(0);
|
507
|
+
}
|
508
|
+
else{
|
509
|
+
ANY2P(args[i]) = DLVOIDP(rb_ary2cary(0, argv[i], NULL));
|
510
|
+
}
|
511
|
+
PUSH_P(ftype);
|
512
|
+
break;
|
513
|
+
case 'C':
|
514
|
+
ANY2C(args[i]) = DLCHAR(NUM2CHR(argv[i]));
|
515
|
+
PUSH_C(ftype);
|
516
|
+
break;
|
517
|
+
case 'c':
|
518
|
+
ANY2C(dargs[i]) = DLCHAR(NUM2CHR(argv[i]));
|
519
|
+
ANY2P(args[i]) = DLVOIDP(&(ANY2C(dargs[i])));
|
520
|
+
dtypes[i] = 'c';
|
521
|
+
PUSH_P(ftype);
|
522
|
+
break;
|
523
|
+
case 'H':
|
524
|
+
ANY2H(args[i]) = DLSHORT(NUM2INT(argv[i]));
|
525
|
+
PUSH_C(ftype);
|
526
|
+
break;
|
527
|
+
case 'h':
|
528
|
+
ANY2H(dargs[i]) = DLSHORT(NUM2INT(argv[i]));
|
529
|
+
ANY2P(args[i]) = DLVOIDP(&(ANY2H(dargs[i])));
|
530
|
+
dtypes[i] = 'h';
|
531
|
+
PUSH_P(ftype);
|
532
|
+
break;
|
533
|
+
case 'I':
|
534
|
+
ANY2I(args[i]) = DLINT(NUM2INT(argv[i]));
|
535
|
+
PUSH_I(ftype);
|
536
|
+
break;
|
537
|
+
case 'i':
|
538
|
+
ANY2I(dargs[i]) = DLINT(NUM2INT(argv[i]));
|
539
|
+
ANY2P(args[i]) = DLVOIDP(&(ANY2I(dargs[i])));
|
540
|
+
dtypes[i] = 'i';
|
541
|
+
PUSH_P(ftype);
|
542
|
+
break;
|
543
|
+
case 'L':
|
544
|
+
ANY2L(args[i]) = DLNUM2LONG(argv[i]);
|
545
|
+
PUSH_L(ftype);
|
546
|
+
break;
|
547
|
+
case 'l':
|
548
|
+
ANY2L(dargs[i]) = DLNUM2LONG(argv[i]);
|
549
|
+
ANY2P(args[i]) = DLVOIDP(&(ANY2L(dargs[i])));
|
550
|
+
dtypes[i] = 'l';
|
551
|
+
PUSH_P(ftype);
|
552
|
+
break;
|
553
|
+
case 'F':
|
554
|
+
Check_Type(argv[i], T_FLOAT);
|
555
|
+
ANY2F(args[i]) = DLFLOAT(RFLOAT(argv[i])->value);
|
556
|
+
PUSH_F(ftype);
|
557
|
+
break;
|
558
|
+
case 'f':
|
559
|
+
Check_Type(argv[i], T_FLOAT);
|
560
|
+
ANY2F(dargs[i]) = DLFLOAT(RFLOAT(argv[i])->value);
|
561
|
+
ANY2P(args[i]) = DLVOIDP(&(ANY2F(dargs[i])));
|
562
|
+
dtypes[i] = 'f';
|
563
|
+
PUSH_P(ftype);
|
564
|
+
break;
|
565
|
+
case 'D':
|
566
|
+
Check_Type(argv[i], T_FLOAT);
|
567
|
+
ANY2D(args[i]) = RFLOAT(argv[i])->value;
|
568
|
+
PUSH_D(ftype);
|
569
|
+
break;
|
570
|
+
case 'd':
|
571
|
+
Check_Type(argv[i], T_FLOAT);
|
572
|
+
ANY2D(dargs[i]) = RFLOAT(argv[i])->value;
|
573
|
+
ANY2P(args[i]) = DLVOIDP(&(ANY2D(dargs[i])));
|
574
|
+
dtypes[i] = 'd';
|
575
|
+
PUSH_P(ftype);
|
576
|
+
break;
|
577
|
+
case 'S':
|
578
|
+
if( argv[i] == Qnil ){
|
579
|
+
ANY2S(args[i]) = DLSTR(0);
|
580
|
+
}
|
581
|
+
else{
|
582
|
+
VALUE str = argv[i];
|
583
|
+
SafeStringValue(str);
|
584
|
+
ANY2S(args[i]) = DLSTR(RSTRING(str)->ptr);
|
585
|
+
}
|
586
|
+
PUSH_P(ftype);
|
587
|
+
break;
|
588
|
+
case 's':
|
589
|
+
{
|
590
|
+
VALUE str = argv[i];
|
591
|
+
SafeStringValue(str);
|
592
|
+
ANY2S(args[i]) = DLSTR(dlmalloc(RSTRING(str)->len + 1));
|
593
|
+
memcpy((char*)(ANY2S(args[i])), RSTRING(str)->ptr, RSTRING(str)->len + 1);
|
594
|
+
dtypes[i] = 's';
|
595
|
+
}
|
596
|
+
PUSH_P(ftype);
|
597
|
+
break;
|
598
|
+
default:
|
599
|
+
FREE_ARGS;
|
600
|
+
rb_raise(rb_eDLTypeError,
|
601
|
+
"unknown type '%c' of the return value.",
|
602
|
+
sym->type[i+1]);
|
603
|
+
}
|
604
|
+
}
|
605
|
+
|
606
|
+
switch( sym->type[0] ){
|
607
|
+
case '0':
|
608
|
+
PUSH_0(ftype);
|
609
|
+
break;
|
610
|
+
case 'P':
|
611
|
+
case 'p':
|
612
|
+
case 'S':
|
613
|
+
case 's':
|
614
|
+
case 'A':
|
615
|
+
case 'a':
|
616
|
+
PUSH_P(ftype);
|
617
|
+
break;
|
618
|
+
case 'C':
|
619
|
+
case 'c':
|
620
|
+
PUSH_C(ftype);
|
621
|
+
break;
|
622
|
+
case 'H':
|
623
|
+
case 'h':
|
624
|
+
PUSH_H(ftype);
|
625
|
+
break;
|
626
|
+
case 'I':
|
627
|
+
case 'i':
|
628
|
+
PUSH_I(ftype);
|
629
|
+
break;
|
630
|
+
case 'L':
|
631
|
+
case 'l':
|
632
|
+
PUSH_L(ftype);
|
633
|
+
break;
|
634
|
+
case 'F':
|
635
|
+
case 'f':
|
636
|
+
PUSH_F(ftype);
|
637
|
+
break;
|
638
|
+
case 'D':
|
639
|
+
case 'd':
|
640
|
+
PUSH_D(ftype);
|
641
|
+
break;
|
642
|
+
default:
|
643
|
+
FREE_ARGS;
|
644
|
+
rb_raise(rb_eDLTypeError,
|
645
|
+
"unknown type `%c' of the return value.",
|
646
|
+
sym->type[0]);
|
647
|
+
}
|
648
|
+
|
649
|
+
func = sym->func;
|
650
|
+
|
651
|
+
#if defined(DLSTACK)
|
652
|
+
{
|
653
|
+
#if defined(DLSTACK_SIZE)
|
654
|
+
int stk_size;
|
655
|
+
long stack[DLSTACK_SIZE];
|
656
|
+
long *sp;
|
657
|
+
|
658
|
+
sp = stack;
|
659
|
+
stk_size = stack_size(sym);
|
660
|
+
if( stk_size < 0 ){
|
661
|
+
FREE_ARGS;
|
662
|
+
rb_raise(rb_eDLTypeError, "unknown type '%c'.", -stk_size);
|
663
|
+
}
|
664
|
+
else if( stk_size > (int)(DLSTACK_SIZE) ){
|
665
|
+
FREE_ARGS;
|
666
|
+
rb_raise(rb_eArgError, "too many arguments.");
|
667
|
+
}
|
668
|
+
#endif
|
669
|
+
|
670
|
+
DLSTACK_START(sym);
|
671
|
+
|
672
|
+
#if defined(DLSTACK_REVERSE)
|
673
|
+
for( i = sym->len - 2; i >= 0; i-- )
|
674
|
+
#else
|
675
|
+
for( i = 0; i <= sym->len -2; i++ )
|
676
|
+
#endif
|
677
|
+
{
|
678
|
+
switch( sym->type[i+1] ){
|
679
|
+
case 'p':
|
680
|
+
case 'P':
|
681
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
682
|
+
break;
|
683
|
+
case 'a':
|
684
|
+
case 'A':
|
685
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
686
|
+
break;
|
687
|
+
case 'C':
|
688
|
+
DLSTACK_PUSH_C(ANY2C(args[i]));
|
689
|
+
break;
|
690
|
+
case 'c':
|
691
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
692
|
+
break;
|
693
|
+
case 'H':
|
694
|
+
DLSTACK_PUSH_H(ANY2H(args[i]));
|
695
|
+
break;
|
696
|
+
case 'h':
|
697
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
698
|
+
break;
|
699
|
+
case 'I':
|
700
|
+
DLSTACK_PUSH_I(ANY2I(args[i]));
|
701
|
+
break;
|
702
|
+
case 'i':
|
703
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
704
|
+
break;
|
705
|
+
case 'L':
|
706
|
+
DLSTACK_PUSH_L(ANY2L(args[i]));
|
707
|
+
break;
|
708
|
+
case 'l':
|
709
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
710
|
+
break;
|
711
|
+
case 'F':
|
712
|
+
DLSTACK_PUSH_F(ANY2F(args[i]));
|
713
|
+
break;
|
714
|
+
case 'f':
|
715
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
716
|
+
break;
|
717
|
+
case 'D':
|
718
|
+
DLSTACK_PUSH_D(ANY2D(args[i]));
|
719
|
+
break;
|
720
|
+
case 'd':
|
721
|
+
DLSTACK_PUSH_P(ANY2P(args[i]));
|
722
|
+
break;
|
723
|
+
case 'S':
|
724
|
+
case 's':
|
725
|
+
DLSTACK_PUSH_P(ANY2S(args[i]));
|
726
|
+
break;
|
727
|
+
}
|
728
|
+
}
|
729
|
+
DLSTACK_END(sym->type);
|
730
|
+
|
731
|
+
#ifdef DLSTACK_GUARD
|
732
|
+
if(!rb_dlsym_guardcall(sym->type[0], &ret, stack, func)) {
|
733
|
+
FREE_ARGS;
|
734
|
+
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
|
735
|
+
}
|
736
|
+
#else /* defined(DLSTACK_GUARD) */
|
737
|
+
{
|
738
|
+
switch( sym->type[0] ){
|
739
|
+
case '0':
|
740
|
+
{
|
741
|
+
void (*f)(DLSTACK_PROTO) = func;
|
742
|
+
f(DLSTACK_ARGS);
|
743
|
+
}
|
744
|
+
break;
|
745
|
+
case 'P':
|
746
|
+
case 'p':
|
747
|
+
{
|
748
|
+
void * (*f)(DLSTACK_PROTO) = func;
|
749
|
+
ret.p = f(DLSTACK_ARGS);
|
750
|
+
}
|
751
|
+
break;
|
752
|
+
case 'C':
|
753
|
+
case 'c':
|
754
|
+
{
|
755
|
+
char (*f)(DLSTACK_PROTO) = func;
|
756
|
+
ret.c = f(DLSTACK_ARGS);
|
757
|
+
}
|
758
|
+
break;
|
759
|
+
case 'H':
|
760
|
+
case 'h':
|
761
|
+
{
|
762
|
+
short (*f)(DLSTACK_PROTO) = func;
|
763
|
+
ret.h = f(DLSTACK_ARGS);
|
764
|
+
}
|
765
|
+
break;
|
766
|
+
case 'I':
|
767
|
+
case 'i':
|
768
|
+
{
|
769
|
+
int (*f)(DLSTACK_PROTO) = func;
|
770
|
+
ret.i = f(DLSTACK_ARGS);
|
771
|
+
}
|
772
|
+
break;
|
773
|
+
case 'L':
|
774
|
+
case 'l':
|
775
|
+
{
|
776
|
+
long (*f)(DLSTACK_PROTO) = func;
|
777
|
+
ret.l = f(DLSTACK_ARGS);
|
778
|
+
}
|
779
|
+
break;
|
780
|
+
case 'F':
|
781
|
+
case 'f':
|
782
|
+
{
|
783
|
+
float (*f)(DLSTACK_PROTO) = func;
|
784
|
+
ret.f = f(DLSTACK_ARGS);
|
785
|
+
}
|
786
|
+
break;
|
787
|
+
case 'D':
|
788
|
+
case 'd':
|
789
|
+
{
|
790
|
+
double (*f)(DLSTACK_PROTO) = func;
|
791
|
+
ret.d = f(DLSTACK_ARGS);
|
792
|
+
}
|
793
|
+
break;
|
794
|
+
case 'S':
|
795
|
+
case 's':
|
796
|
+
{
|
797
|
+
char * (*f)(DLSTACK_PROTO) = func;
|
798
|
+
ret.s = f(DLSTACK_ARGS);
|
799
|
+
}
|
800
|
+
break;
|
801
|
+
default:
|
802
|
+
FREE_ARGS;
|
803
|
+
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
|
804
|
+
}
|
805
|
+
}
|
806
|
+
#endif /* defubed(DLSTACK_GUARD) */
|
807
|
+
|
808
|
+
{
|
809
|
+
/*
|
810
|
+
* We should get the value of errno/GetLastError() before calling another functions.
|
811
|
+
*/
|
812
|
+
int last_errno = errno;
|
813
|
+
#ifdef _WIN32
|
814
|
+
DWORD win32_last_err = GetLastError();
|
815
|
+
#endif
|
816
|
+
|
817
|
+
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, INT2NUM(last_errno));
|
818
|
+
#ifdef _WIN32
|
819
|
+
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, INT2NUM(win32_last_err));
|
820
|
+
#endif
|
821
|
+
}
|
822
|
+
|
823
|
+
}
|
824
|
+
#else /* defined(DLSTACK) */
|
825
|
+
switch(ftype){
|
826
|
+
#include "call.func"
|
827
|
+
default:
|
828
|
+
FREE_ARGS;
|
829
|
+
rb_raise(rb_eDLTypeError, "unsupported function type `%s'", sym->type);
|
830
|
+
}
|
831
|
+
#endif /* defined(DLSTACK) */
|
832
|
+
|
833
|
+
switch( sym->type[0] ){
|
834
|
+
case '0':
|
835
|
+
val = Qnil;
|
836
|
+
break;
|
837
|
+
case 'P':
|
838
|
+
val = rb_dlptr_new((void*)(ANY2P(ret)), 0, 0);
|
839
|
+
break;
|
840
|
+
case 'p':
|
841
|
+
val = rb_dlptr_new((void*)(ANY2P(ret)), 0, dlfree);
|
842
|
+
break;
|
843
|
+
case 'C':
|
844
|
+
case 'c':
|
845
|
+
val = CHR2FIX((char)(ANY2C(ret)));
|
846
|
+
break;
|
847
|
+
case 'H':
|
848
|
+
case 'h':
|
849
|
+
val = INT2NUM((short)(ANY2H(ret)));
|
850
|
+
break;
|
851
|
+
case 'I':
|
852
|
+
case 'i':
|
853
|
+
val = INT2NUM((int)(ANY2I(ret)));
|
854
|
+
break;
|
855
|
+
case 'L':
|
856
|
+
case 'l':
|
857
|
+
val = DLLONG2NUM((long)(ANY2L(ret)));
|
858
|
+
break;
|
859
|
+
case 'F':
|
860
|
+
case 'f':
|
861
|
+
val = rb_float_new((double)(ANY2F(ret)));
|
862
|
+
break;
|
863
|
+
case 'D':
|
864
|
+
case 'd':
|
865
|
+
val = rb_float_new((double)(ANY2D(ret)));
|
866
|
+
break;
|
867
|
+
case 'S':
|
868
|
+
if( ANY2S(ret) ){
|
869
|
+
val = rb_tainted_str_new2((char*)(ANY2S(ret)));
|
870
|
+
}
|
871
|
+
else{
|
872
|
+
val = Qnil;
|
873
|
+
}
|
874
|
+
break;
|
875
|
+
case 's':
|
876
|
+
if( ANY2S(ret) ){
|
877
|
+
val = rb_tainted_str_new2((char*)(ANY2S(ret)));
|
878
|
+
DEBUG_CODE({
|
879
|
+
printf("dlfree(%s)\n",(char*)(ANY2S(ret)));
|
880
|
+
});
|
881
|
+
dlfree((void*)(ANY2S(ret)));
|
882
|
+
}
|
883
|
+
else{
|
884
|
+
val = Qnil;
|
885
|
+
}
|
886
|
+
break;
|
887
|
+
default:
|
888
|
+
FREE_ARGS;
|
889
|
+
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
|
890
|
+
}
|
891
|
+
|
892
|
+
dvals = rb_ary_new();
|
893
|
+
for( i = 0; i <= sym->len - 2; i++ ){
|
894
|
+
if( dtypes[i] ){
|
895
|
+
switch( dtypes[i] ){
|
896
|
+
case 'c':
|
897
|
+
rb_ary_push(dvals, CHR2FIX(*((char*)(ANY2P(args[i])))));
|
898
|
+
break;
|
899
|
+
case 'h':
|
900
|
+
rb_ary_push(dvals, INT2NUM(*((short*)(ANY2P(args[i])))));
|
901
|
+
break;
|
902
|
+
case 'i':
|
903
|
+
rb_ary_push(dvals, INT2NUM(*((int*)(ANY2P(args[i])))));
|
904
|
+
break;
|
905
|
+
case 'l':
|
906
|
+
rb_ary_push(dvals, DLLONG2NUM(*((long*)(ANY2P(args[i])))));
|
907
|
+
break;
|
908
|
+
case 'f':
|
909
|
+
rb_ary_push(dvals, rb_float_new(*((float*)(ANY2P(args[i])))));
|
910
|
+
break;
|
911
|
+
case 'd':
|
912
|
+
rb_ary_push(dvals, rb_float_new(*((double*)(ANY2P(args[i])))));
|
913
|
+
break;
|
914
|
+
case 'p':
|
915
|
+
rb_ary_push(dvals, rb_dlptr_new((void*)(ANY2P(args[i])), 0, 0));
|
916
|
+
break;
|
917
|
+
case 'a':
|
918
|
+
rb_ary_push(dvals, rb_dlptr_new((void*)ANY2P(args[i]), 0, 0));
|
919
|
+
break;
|
920
|
+
case 's':
|
921
|
+
rb_ary_push(dvals, rb_tainted_str_new2((char*)ANY2S(args[i])));
|
922
|
+
DEBUG_CODE({
|
923
|
+
printf("dlfree(%s)\n",(char*)ANY2S(args[i]));
|
924
|
+
});
|
925
|
+
dlfree((void*)ANY2S(args[i]));
|
926
|
+
break;
|
927
|
+
default:
|
928
|
+
{
|
929
|
+
char c = dtypes[i];
|
930
|
+
FREE_ARGS;
|
931
|
+
rb_raise(rb_eRuntimeError, "unknown argument type '%c'", i, c);
|
932
|
+
}
|
933
|
+
}
|
934
|
+
}
|
935
|
+
else{
|
936
|
+
switch( sym->type[i+1] ){
|
937
|
+
case 'A':
|
938
|
+
dlfree((void*)ANY2P(args[i]));
|
939
|
+
break;
|
940
|
+
}
|
941
|
+
rb_ary_push(dvals, argv[i]);
|
942
|
+
}
|
943
|
+
}
|
944
|
+
|
945
|
+
FREE_ARGS;
|
946
|
+
#undef FREE_ARGS
|
947
|
+
return rb_assoc_new(val,dvals);
|
948
|
+
}
|
949
|
+
|
950
|
+
VALUE
|
951
|
+
rb_dlsym_to_i(VALUE self)
|
952
|
+
{
|
953
|
+
struct sym_data *sym;
|
954
|
+
|
955
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
956
|
+
return DLLONG2NUM(sym);
|
957
|
+
}
|
958
|
+
|
959
|
+
VALUE
|
960
|
+
rb_dlsym_to_ptr(VALUE self)
|
961
|
+
{
|
962
|
+
struct sym_data *sym;
|
963
|
+
|
964
|
+
Data_Get_Struct(self, struct sym_data, sym);
|
965
|
+
return rb_dlptr_new(sym->func, sizeof(freefunc_t), 0);
|
966
|
+
}
|
967
|
+
|
968
|
+
void
|
969
|
+
Init_dlsym()
|
970
|
+
{
|
971
|
+
rb_cDLSymbol = rb_define_class_under(rb_mDL, "Symbol", rb_cObject);
|
972
|
+
rb_define_alloc_func(rb_cDLSymbol, rb_dlsym_s_allocate);
|
973
|
+
rb_define_singleton_method(rb_cDLSymbol, "char2type", rb_s_dlsym_char2type, 1);
|
974
|
+
rb_define_method(rb_cDLSymbol, "initialize", rb_dlsym_initialize, -1);
|
975
|
+
rb_define_method(rb_cDLSymbol, "call", rb_dlsym_call, -1);
|
976
|
+
rb_define_method(rb_cDLSymbol, "[]", rb_dlsym_call, -1);
|
977
|
+
rb_define_method(rb_cDLSymbol, "name", rb_dlsym_name, 0);
|
978
|
+
rb_define_method(rb_cDLSymbol, "proto", rb_dlsym_proto, 0);
|
979
|
+
rb_define_method(rb_cDLSymbol, "cproto", rb_dlsym_cproto, 0);
|
980
|
+
rb_define_method(rb_cDLSymbol, "inspect", rb_dlsym_inspect, 0);
|
981
|
+
rb_define_method(rb_cDLSymbol, "to_s", rb_dlsym_cproto, 0);
|
982
|
+
rb_define_method(rb_cDLSymbol, "to_ptr", rb_dlsym_to_ptr, 0);
|
983
|
+
rb_define_method(rb_cDLSymbol, "to_i", rb_dlsym_to_i, 0);
|
984
|
+
|
985
|
+
rb_dl_id_DLErrno = rb_intern("DLErrno");
|
986
|
+
rb_define_singleton_method(rb_mDL, "last_error", rb_dl_get_last_error, 0);
|
987
|
+
rb_define_singleton_method(rb_mDL, "last_error=", rb_dl_set_last_error, 1);
|
988
|
+
#ifdef _WIN32
|
989
|
+
rb_dl_id_DLW32Error = rb_intern("DLW32Error");
|
990
|
+
rb_define_singleton_method(rb_mDL, "win32_last_error", rb_dl_win32_get_last_error, 0);
|
991
|
+
rb_define_singleton_method(rb_mDL, "win32_last_error=", rb_dl_win32_set_last_error, 1);
|
992
|
+
#endif
|
993
|
+
}
|