annotate ruby/rbdc/rbdc.c @ 39:b6114d9a9a98

- shdc: more sig chars for call conv mode selection - readme cleanup
author Tassilo Philipp
date Mon, 13 Apr 2020 21:58:48 +0200
parents 02a455de2b40
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
1 /*
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
2
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
3 rbdc.c
25
02a455de2b40 - 1.0 updates
Tassilo Philipp
parents: 6
diff changeset
4 Copyright (c) 2007-2018 Daniel Adler <dadler@uni-goettingen.de>,
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
5 Tassilo Philipp <tphilipp@potion-studios.com>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
6
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
7 Permission to use, copy, modify, and distribute this software for any
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
8 purpose with or without fee is hereby granted, provided that the above
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
9 copyright notice and this permission notice appear in all copies.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
10
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
11 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
12 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
13 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
14 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
15 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
16 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
17 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
18
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
19 Ruby/dyncall extension implementation.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
20
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
21 */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
22
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
23
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
24 #include <ruby.h>
6
80273969f043 - ruby binding path cleanup, previous version required bindings and dyncall be checked out in same parent directory
cslag
parents: 1
diff changeset
25 #include "dyncall/dyncall/dyncall.h"
80273969f043 - ruby binding path cleanup, previous version required bindings and dyncall be checked out in same parent directory
cslag
parents: 1
diff changeset
26 #include "dyncall/dyncallback/dyncall_callback.h"
80273969f043 - ruby binding path cleanup, previous version required bindings and dyncall be checked out in same parent directory
cslag
parents: 1
diff changeset
27 #include "dyncall/dynload/dynload.h"
80273969f043 - ruby binding path cleanup, previous version required bindings and dyncall be checked out in same parent directory
cslag
parents: 1
diff changeset
28 #include "dyncall/dyncall/dyncall_signature.h"
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
29
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
30 /* Our ruby module and its classes. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
31 static VALUE rb_dcModule;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
32 static VALUE rb_dcExtLib;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
33
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
34
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
35 typedef struct {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
36 void* lib;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
37 void* syms;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
38 DCCallVM* cvm;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
39 } rb_dcLibHandle;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
40
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
41
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
42 /* Allocator for handle and mark-and-sweep GC handlers. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
43 static void GCMark_ExtLib(rb_dcLibHandle* h)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
44 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
45 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
46
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
47 static void GCSweep_ExtLib(rb_dcLibHandle* h)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
48 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
49 if(h->lib != NULL) dlFreeLibrary(h->lib);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
50 if(h->syms != NULL) dlSymsCleanup(h->syms);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
51
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
52 dcFree(h->cvm);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
53 free(h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
54 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
55
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
56 static VALUE AllocExtLib(VALUE cl)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
57 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
58 rb_dcLibHandle* h = malloc(sizeof(rb_dcLibHandle));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
59 h->lib = NULL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
60 h->syms = NULL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
61 h->cvm = dcNewCallVM(4096/*@@@*/);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
62 return Data_Wrap_Struct(cl, GCMark_ExtLib, GCSweep_ExtLib, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
63 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
64
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
65
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
66 /* Helpers */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
67 static void ExtLib_SecCheckLib(rb_dcLibHandle* h)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
68 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
69 if(h->lib == NULL)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
70 rb_raise(rb_eRuntimeError, "no library loaded - use ExtLib#load");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
71 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
72
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
73 static void ExtLib_SecCheckSyms(rb_dcLibHandle* h)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
74 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
75 if(h->syms == NULL)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
76 rb_raise(rb_eRuntimeError, "no symbol table initialized - use ExtLib#symsInit");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
77 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
78
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
79
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
80
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
81 /* Methods for lib access */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
82 static VALUE ExtLib_Load(VALUE self, VALUE path)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
83 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
84 void* newLib;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
85 rb_dcLibHandle* h;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
86
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
87 if(TYPE(path) != T_STRING)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
88 rb_raise(rb_eRuntimeError, "argument must be of type 'String'");/*@@@ respond to to_s*/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
89
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
90 Data_Get_Struct(self, rb_dcLibHandle, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
91 newLib = dlLoadLibrary(RSTRING_PTR(path));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
92 if(newLib) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
93 dlFreeLibrary(h->lib);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
94 h->lib = newLib;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
95
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
96 return self;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
97 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
98
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
99 return Qnil;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
100 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
101
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
102 static VALUE ExtLib_ExistsQ(VALUE self, VALUE sym)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
103 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
104 rb_dcLibHandle* h;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
105
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
106 Data_Get_Struct(self, rb_dcLibHandle, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
107 ExtLib_SecCheckLib(h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
108
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
109 return dlFindSymbol(h->lib, rb_id2name(SYM2ID(sym))) ? Qtrue : Qfalse;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
110 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
111
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
112
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
113 /* Methods for syms parsing */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
114 static VALUE ExtLib_SymsInit(VALUE self, VALUE path)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
115 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
116 void* newSyms;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
117 rb_dcLibHandle* h;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
118
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
119 if(TYPE(path) != T_STRING)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
120 rb_raise(rb_eRuntimeError, "argument must be of type 'String'");/*@@@ respond to to_s*/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
121
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
122 Data_Get_Struct(self, rb_dcLibHandle, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
123 newSyms = dlSymsInit(RSTRING_PTR(path));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
124
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
125 if(newSyms) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
126 dlSymsCleanup(h->syms);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
127 h->syms = newSyms;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
128
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
129 return self;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
130 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
131
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
132 return Qnil;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
133 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
134
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
135
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
136 static VALUE ExtLib_SymsCount(VALUE self)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
137 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
138 rb_dcLibHandle* h;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
139
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
140 Data_Get_Struct(self, rb_dcLibHandle, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
141 ExtLib_SecCheckSyms(h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
142
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
143 return LONG2NUM(dlSymsCount(h->syms));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
144 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
145
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
146
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
147 static VALUE ExtLib_SymsEach(int argc, VALUE* argv, VALUE self)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
148 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
149 rb_dcLibHandle* h;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
150 size_t i, c;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
151
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
152 if(!rb_block_given_p())
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
153 rb_raise(rb_eRuntimeError, "no block given");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
154
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
155 Data_Get_Struct(self, rb_dcLibHandle, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
156 ExtLib_SecCheckSyms(h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
157
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
158 c = dlSymsCount(h->syms);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
159 for(i=0; i<c; ++i)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
160 rb_yield(ID2SYM(rb_intern(dlSymsName(h->syms, i))));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
161
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
162 return self;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
163 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
164
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
165 /* expose dlSymsName @@@ */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
166
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
167
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
168 /* Methods interfacing with dyncall */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
169 static VALUE ExtLib_Call(int argc, VALUE* argv, VALUE self)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
170 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
171 /* argv[0] - symbol to call *
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
172 * argv[1] - signature *
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
173 * argv[2] - first parameter *
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
174 * argv[x] - parameter x-2 */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
175
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
176 rb_dcLibHandle* h;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
177 DCpointer fptr;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
178 int i, t, b;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
179 VALUE r;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
180 DCCallVM* cvm;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
181 const char* sig;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
182
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
183
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
184 /* Security checks. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
185 if(argc < 2)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
186 rb_raise(rb_eRuntimeError, "wrong number of arguments for function call");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
187
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
188 if(TYPE(argv[0]) != T_SYMBOL)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
189 rb_raise(rb_eRuntimeError, "syntax error - argument 0 must be of type 'Symbol'");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
190
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
191 if(TYPE(argv[1]) != T_STRING)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
192 rb_raise(rb_eRuntimeError, "syntax error - argument 1 must be of type 'String'");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
193
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
194 Data_Get_Struct(self, rb_dcLibHandle, h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
195 cvm = h->cvm;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
196
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
197 if(argc != RSTRING_LEN(argv[1])) /* Don't count the return value in the signature @@@ write something more secure */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
198 rb_raise(rb_eRuntimeError, "number of provided arguments doesn't match signature");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
199
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
200 ExtLib_SecCheckLib(h);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
201
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
202
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
203 /* Flush old arguments. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
204 dcReset(cvm);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
205
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
206
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
207 /* Get a pointer to the function and start pushing. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
208 fptr = (DCpointer)dlFindSymbol(h->lib, rb_id2name(SYM2ID(argv[0])));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
209 sig = RSTRING_PTR(argv[1]);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
210
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
211 for(i=2; i<argc; ++i) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
212 t = TYPE(argv[i]);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
213
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
214 //@@@ add support for calling convention mode(s)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
215
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
216 switch(sig[i-2]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
217 case DC_SIGCHAR_BOOL:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
218 b = 1;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
219 switch(t) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
220 case T_TRUE: dcArgBool(cvm, DC_TRUE); break; /* TrueClass. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
221 case T_FALSE: /* FalseClass. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
222 case T_NIL: dcArgBool(cvm, DC_FALSE); break; /* NilClass. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
223 case T_FIXNUM: dcArgBool(cvm, FIX2LONG(argv[i]) != 0); break; /* Fixnum. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
224 default: b = 0; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
225 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
226 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
227
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
228 case DC_SIGCHAR_CHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
229 case DC_SIGCHAR_UCHAR: if(b = (t == T_FIXNUM)) dcArgChar (cvm, (DCchar) FIX2LONG(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
230 case DC_SIGCHAR_SHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
231 case DC_SIGCHAR_USHORT: if(b = (t == T_FIXNUM)) dcArgShort (cvm, (DCshort) FIX2LONG(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
232 case DC_SIGCHAR_INT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
233 case DC_SIGCHAR_UINT: if(b = (t == T_FIXNUM)) dcArgInt (cvm, (DCint) FIX2LONG(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
234 case DC_SIGCHAR_LONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
235 case DC_SIGCHAR_ULONG: if(b = (t == T_FIXNUM)) dcArgLong (cvm, (DClong) FIX2LONG(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
236 case DC_SIGCHAR_LONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
237 case DC_SIGCHAR_ULONGLONG: if(b = (t == T_FIXNUM)) dcArgLongLong(cvm, (DClonglong)FIX2LONG(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
238 case DC_SIGCHAR_FLOAT: if(b = (t == T_FLOAT)) dcArgFloat (cvm, (DCfloat) RFLOAT_VALUE(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
239 case DC_SIGCHAR_DOUBLE: if(b = (t == T_FLOAT)) dcArgDouble (cvm, (DCdouble) RFLOAT_VALUE(argv[i])); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
240
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
241 case DC_SIGCHAR_POINTER:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
242 case DC_SIGCHAR_STRING:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
243 b = 1;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
244 switch(t) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
245 case T_STRING: dcArgPointer(cvm, RSTRING_PTR(argv[i])); break; /* String. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
246 default: b = 0; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
247 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
248 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
249
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
250 default:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
251 b = 0;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
252 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
253 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
254
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
255
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
256 if(!b)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
257 rb_raise(rb_eRuntimeError, "syntax error in signature or type mismatch at argument %d", i-2);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
258 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
259
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
260
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
261 /* Get the return type and call the function. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
262 switch(sig[i-1]) {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
263 case DC_SIGCHAR_VOID: r = Qnil; dcCallVoid (cvm, fptr); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
264 case DC_SIGCHAR_BOOL: r = dcCallBool (cvm, fptr) ? Qtrue : Qfalse; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
265 case DC_SIGCHAR_CHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
266 case DC_SIGCHAR_UCHAR: r = CHR2FIX( dcCallChar (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
267 case DC_SIGCHAR_SHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
268 case DC_SIGCHAR_USHORT: r = INT2FIX( dcCallShort (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
269 case DC_SIGCHAR_INT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
270 case DC_SIGCHAR_UINT: r = INT2FIX( dcCallInt (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
271 case DC_SIGCHAR_LONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
272 case DC_SIGCHAR_ULONG: r = INT2FIX( dcCallLong (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
273 case DC_SIGCHAR_LONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
274 case DC_SIGCHAR_ULONGLONG: r = INT2FIX( dcCallLongLong(cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
275 case DC_SIGCHAR_FLOAT: r = rb_float_new(dcCallFloat (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
276 case DC_SIGCHAR_DOUBLE: r = rb_float_new(dcCallDouble (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
277 case DC_SIGCHAR_STRING: r = rb_str_new2( dcCallPointer (cvm, fptr)); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
278 case DC_SIGCHAR_POINTER:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
279 default:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
280 rb_raise(rb_eRuntimeError, "unsupported return type or syntax error in signature");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
281 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
282
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
283 return r;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
284 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
285
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
286
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
287 /* Main initialization. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
288 void Init_rbdc()
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
289 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
290 rb_dcModule = rb_define_module("Dyncall");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
291
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
292 /* Handle to the external dynamic library. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
293 rb_dcExtLib = rb_define_class_under(rb_dcModule, "ExtLib", rb_cObject);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
294
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
295 /* Class allocators. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
296 rb_define_alloc_func(rb_dcExtLib, AllocExtLib);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
297
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
298 /* Methods. */
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
299 rb_define_method(rb_dcExtLib, "load", &ExtLib_Load, 1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
300 rb_define_method(rb_dcExtLib, "exists?", &ExtLib_ExistsQ, 1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
301 rb_define_method(rb_dcExtLib, "syms_init", &ExtLib_SymsInit, 1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
302 rb_define_method(rb_dcExtLib, "syms_count", &ExtLib_SymsCount, 0);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
303 rb_define_method(rb_dcExtLib, "syms_each", &ExtLib_SymsEach, -1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
304 rb_define_method(rb_dcExtLib, "call", &ExtLib_Call, -1);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
305 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
306