17
17
#include <stdbool.h>
18
18
#include "ffi.h"
19
19
20
+ #ifdef _WIN32
21
+ #include <windows.h>
22
+ static void *
23
+ get_proc_address (const char * funcname )
24
+ {
25
+ HINSTANCE hInst = GetModuleHandle (NULL );
26
+ PBYTE pImage = (PBYTE ) hInst ;
27
+ PIMAGE_DOS_HEADER pDOS = (PIMAGE_DOS_HEADER ) hInst ;
28
+ PIMAGE_NT_HEADERS pPE ;
29
+ PIMAGE_IMPORT_DESCRIPTOR pImpDesc ;
30
+
31
+ if (pDOS -> e_magic != IMAGE_DOS_SIGNATURE )
32
+ return NULL ;
33
+ pPE = (PIMAGE_NT_HEADERS )(pImage + pDOS -> e_lfanew );
34
+ if (pPE -> Signature != IMAGE_NT_SIGNATURE )
35
+ return NULL ;
36
+ pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR )(pImage
37
+ + pPE -> OptionalHeader .DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT ].VirtualAddress );
38
+ for (; pImpDesc -> FirstThunk ; ++ pImpDesc ) {
39
+ HINSTANCE hLib = LoadLibrary ((const char * )(pImage + pImpDesc -> Name ));
40
+ if (hLib ) {
41
+ void * p = GetProcAddress (hLib , "strcpy" );
42
+ if (p ) return p ;
43
+ }
44
+ }
45
+ return NULL ;
46
+ }
47
+ #endif
20
48
21
49
static mrb_value
22
50
cfunc_call (mrb_state * mrb , mrb_value self )
@@ -25,14 +53,18 @@ cfunc_call(mrb_state *mrb, mrb_value self)
25
53
mrb_value mresult_type , mname , * margs ;
26
54
void * * values = NULL ;
27
55
ffi_type * * args = NULL ;
28
-
56
+
29
57
mrb_get_args (mrb , "oo*" , & mresult_type , & mname , & margs , & margc );
30
-
58
+
31
59
void * fp = NULL ;
32
60
if (mrb_string_p (mname ) || mrb_symbol_p (mname )) {
61
+ #ifndef _WIN32
33
62
void * dlh = dlopen (NULL , RTLD_LAZY );
34
63
fp = dlsym (dlh , mrb_string_value_ptr (mrb , mname ));
35
64
dlclose (dlh );
65
+ #else
66
+ fp = get_proc_address (mrb_string_value_ptr (mrb , mname ));
67
+ #endif
36
68
37
69
if (fp == NULL ) {
38
70
mrb_raisef (mrb , E_NAME_ERROR , "can't find C function %s" , mrb_string_value_ptr (mrb , mname ));
@@ -103,7 +135,93 @@ cfunc_call(mrb_state *mrb, mrb_value self)
103
135
}
104
136
105
137
138
+ static mrb_value
139
+ cfunc_libcall (mrb_state * mrb , mrb_value self )
140
+ {
141
+ int margc ;
142
+ mrb_value mresult_type , mlib , mname , * margs ;
143
+ void * * values = NULL ;
144
+ ffi_type * * args = NULL ;
145
+
146
+ mrb_get_args (mrb , "oSo*" , & mresult_type , & mlib , & mname , & margs , & margc );
147
+
148
+ void * fp = NULL ;
149
+ if ((mrb_string_p (mname ) || mrb_symbol_p (mname ))) {
150
+ void * dlh = dlopen (mrb_string_value_ptr (mrb , mlib ), RTLD_LAZY );
151
+ fp = dlsym (dlh , mrb_string_value_ptr (mrb , mname ));
152
+ dlclose (dlh );
153
+
154
+ if (fp == NULL ) {
155
+ mrb_raisef (mrb , E_NAME_ERROR , "can't find C function %s" , mrb_string_value_ptr (mrb , mname ));
156
+ goto cfunc_call_exit ;
157
+ }
158
+ }
159
+ else {
160
+ fp = cfunc_pointer_ptr (mname );
161
+ if (fp == NULL ) {
162
+ mrb_raisef (mrb , E_NAME_ERROR , "can't call NULL pointer" );
163
+ goto cfunc_call_exit ;
164
+ }
165
+ }
166
+
167
+ args = malloc (sizeof (ffi_type * ) * margc );
168
+ values = malloc (sizeof (void * ) * margc );
169
+ mrb_sym sym_to_ffi_value = mrb_intern (mrb , "to_ffi_value" );
170
+
171
+ mrb_value nil_ary [1 ];
172
+ nil_ary [0 ] = mrb_nil_value ();
173
+ int i ;
174
+ for (i = 0 ; i < margc ; ++ i ) {
175
+ if (mrb_respond_to (mrb , margs [i ], sym_to_ffi_value )) {
176
+ args [i ] = mrb_value_to_mrb_ffi_type (mrb , margs [i ])-> ffi_type_value ;
177
+ values [i ] = cfunc_pointer_ptr (mrb_funcall_argv (mrb , margs [i ], sym_to_ffi_value , 1 , nil_ary ));
178
+ }
179
+ else {
180
+ cfunc_mrb_raise_without_jump (mrb , E_TYPE_ERROR , "ignore argument type %s" , mrb_obj_classname (mrb , margs [i ]));
181
+ goto cfunc_call_exit ;
182
+ }
183
+ }
184
+
185
+ ffi_type * result_type = rclass_to_mrb_ffi_type (mrb , mrb_class_ptr (mresult_type ))-> ffi_type_value ;
186
+ if (result_type == NULL ) {
187
+ cfunc_mrb_raise_without_jump (mrb , E_ARGUMENT_ERROR , "ignore return type %s" , mrb_class_name (mrb , mrb_class_ptr (mresult_type )));
188
+ goto cfunc_call_exit ;
189
+ }
190
+
191
+ mrb_value mresult = mrb_nil_value ();
192
+ ffi_cif cif ;
193
+ if (ffi_prep_cif (& cif , FFI_DEFAULT_ABI , margc , result_type , args ) == FFI_OK ) {
194
+ void * result ;
195
+ if (result_type -> size > sizeof (long )) {
196
+ result = malloc (result_type -> size );
197
+ }
198
+ else if (result_type -> size ) {
199
+ result = malloc (sizeof (long ));
200
+ }
201
+ else {
202
+ result = NULL ;
203
+ }
204
+ ffi_call (& cif , fp , result , values );
205
+
206
+ if (result ) {
207
+ mrb_value result_ptr = cfunc_pointer_new_with_pointer (mrb , result , true);
208
+ mresult = mrb_funcall (mrb , mresult_type , "refer" , 1 , result_ptr );
209
+ }
210
+ }
211
+ else {
212
+ mrb_raisef (mrb , E_NAME_ERROR , "Can't find C function %s" , mname );
213
+ goto cfunc_call_exit ;
214
+ }
215
+
216
+ cfunc_call_exit :
217
+ free (values );
218
+ free (args );
219
+ return mresult ;
220
+ }
221
+
222
+
106
223
void init_cfunc_call (mrb_state * mrb , struct RClass * module )
107
224
{
108
225
mrb_define_class_method (mrb , module , "call" , cfunc_call , ARGS_ANY ());
226
+ mrb_define_module_function (mrb , module , "libcall" , cfunc_libcall , ARGS_ANY ());
109
227
}
0 commit comments