rjb 1.1.0-x86-mswin32-60

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.
@@ -0,0 +1,225 @@
1
+ /*
2
+ * Rjb - Ruby <-> Java Bridge
3
+ * Copyright(c) 2004 Kuwashima
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * $Id: riconv.c 45 2007-12-26 20:03:21Z kuwa1 $
16
+ */
17
+
18
+ #include "ruby.h"
19
+ #include "extconf.h"
20
+
21
+ #if defined _WIN32 || defined __CYGWIN__
22
+ #include <windows.h>
23
+ #endif
24
+
25
+ #if defined HAVE_NL_LANGINFO
26
+ #include <langinfo.h>
27
+ static const char* const NL_EUC_TABLE[] = { "EUC-JISX0213", "EUC-JP", "EUC-JP-MS" };
28
+ static const char* const NL_SJIS_TABLE[] = { "SHIFT_JIS", "SHIFT_JISX0213", "WINDOWS-31J" };
29
+ #endif
30
+
31
+ #if defined HAVE_SETLOCALE
32
+ #include <locale.h>
33
+ static const char* const LOCALE_EUC_TABLE[] = { "japanese", "ja_JP.eucJP", "japanese.euc", "ja_JP", "ja_JP.ujis" };
34
+ static const char* const LOCALE_SJIS_TABLE[] = { "japanese.sjis", "ja_JP.SJIS" };
35
+ static const char* const LOCALE_UTF8_TABLE[] = { "ja_JP.UTF-8", "ja_JP.utf8" };
36
+ #endif
37
+
38
+ #include "riconv.h"
39
+
40
+ static const char* const CS_EUCJP = "EUC-JP";
41
+ static const char* const CS_CP932 = "CP932";
42
+ static const char* const CS_SJIS = "SHIFT_JIS";
43
+ static const char* const CS_UTF8 = "UTF-8";
44
+
45
+
46
+ static VALUE objIconvJ2R;
47
+ static VALUE objIconvR2J;
48
+ static const char* charcode; //is this necessary?
49
+ static char Kcode = '\0';
50
+
51
+ static int find_table(const char* const str, const char* const table[])
52
+ {
53
+ int i;
54
+ int size = sizeof(table) / sizeof(table[0]);
55
+ for (i = 0; i < size; ++i)
56
+ {
57
+ if (strstr(str, table[i])) return 1;
58
+ }
59
+ return 0;
60
+ }
61
+
62
+ static const char* get_charcode_name_by_locale(const char* const name)
63
+ {
64
+ if (find_table(name, LOCALE_UTF8_TABLE))
65
+ return NULL;
66
+ else if (find_table(name, LOCALE_EUC_TABLE))
67
+ return CS_EUCJP;
68
+ else if (find_table(name, LOCALE_SJIS_TABLE))
69
+ return CS_SJIS;
70
+ else
71
+ return NULL;
72
+ }
73
+ /*
74
+ * Get better charcode name.
75
+ */
76
+ static const char* get_charcode_name()
77
+ {
78
+ const char* result = NULL;
79
+ const char* lang = NULL;
80
+
81
+ switch(Kcode)
82
+ {
83
+ case 'E':
84
+ result = CS_EUCJP;
85
+ break;
86
+ case 'S':
87
+ #if defined _WIN32 || defined __CYGWIN__
88
+ result = CS_CP932;
89
+ #else
90
+ result = CS_SJIS;
91
+ #endif
92
+ break;
93
+ case 'U':
94
+ //as is.
95
+ break;
96
+ case 'N':
97
+ default:
98
+ #if defined _WIN32 || defined __CYGWIN__
99
+ if (932 == GetACP()) result = CS_CP932;
100
+ #elif defined HAVE_NL_LANGINFO
101
+ setlocale(LC_ALL, ""); //initialize
102
+ lang = nl_langinfo(CODESET);
103
+ if (find_table(lang, NL_EUC_TABLE))
104
+ result = CS_EUCJP;
105
+ else if (find_table(lang, NL_SJIS_TABLE))
106
+ result = CS_SJIS;
107
+ #elif defined HAVE_SETLOCALE
108
+ setlocale(LC_ALL, ""); //initialize
109
+ result = get_charcode_name_by_locale(setlocale(LC_ALL, NULL));
110
+ #elif defined HAVE_GETENV
111
+ printf("HAVE_GETENV\n");
112
+ if (result = get_charcode_name_by_locale(getenv("LC_ALL")))
113
+ ;
114
+ else if (result = get_charcode_name_by_locale(getenv("LC_CTYPE")))
115
+ ;
116
+ else if (result = get_charcode_name_by_locale(getenv("LANG")))
117
+ ;
118
+ #endif
119
+ break;
120
+ }
121
+ return result;
122
+ }
123
+
124
+
125
+ static void reinit()
126
+ {
127
+ charcode = get_charcode_name();
128
+ if (charcode)
129
+ {
130
+ VALUE rb_iconv_klass = rb_const_get(rb_cObject, rb_intern("Iconv"));
131
+ if (RTEST(rb_iconv_klass)) {
132
+ ID sym_new = rb_intern("new");
133
+ rb_gc_unregister_address(&objIconvR2J);
134
+ objIconvR2J = rb_funcall(rb_iconv_klass, sym_new, 2, rb_str_new2(CS_UTF8), rb_str_new2(charcode));
135
+ rb_gc_register_address(&objIconvR2J);
136
+ rb_gc_unregister_address(&objIconvJ2R);
137
+ objIconvJ2R = rb_funcall(rb_iconv_klass, sym_new, 2, rb_str_new2(charcode), rb_str_new2(CS_UTF8));
138
+ rb_gc_register_address(&objIconvJ2R);
139
+ }
140
+ }
141
+ else
142
+ {
143
+ objIconvR2J = objIconvJ2R = Qnil;
144
+ }
145
+ }
146
+
147
+ static void check_kcode()
148
+ {
149
+ VALUE rb_iconv_klass = rb_const_get(rb_cObject, rb_intern("Iconv"));
150
+ VALUE kcode = rb_gv_get("$KCODE");
151
+ if (RTEST(rb_iconv_klass) && TYPE(kcode) == T_STRING) {
152
+ char* kcodep = StringValuePtr(kcode);
153
+ char upper_kcode = toupper(*kcodep);
154
+ if (Kcode != upper_kcode)
155
+ {
156
+ Kcode = upper_kcode;
157
+ reinit();
158
+ }
159
+ }
160
+ else
161
+ {
162
+ objIconvR2J = objIconvJ2R = Qnil;
163
+ }
164
+ }
165
+
166
+ VALUE exticonv_local_to_utf8(VALUE local_string)
167
+ {
168
+ #if RJB_RUBY_VERSION_CODE < 190
169
+ check_kcode();
170
+ if(RTEST(objIconvR2J))
171
+ {
172
+ return rb_funcall(objIconvR2J, rb_intern("iconv"), 1, local_string);
173
+ }
174
+ else
175
+ {
176
+ return local_string;
177
+ }
178
+ #else
179
+ VALUE rb_cEncoding, default_external, encoding, ascii8bit;
180
+ rb_cEncoding = rb_const_get(rb_cObject, rb_intern("Encoding"));
181
+ default_external = rb_funcall(rb_cEncoding, rb_intern("default_external"), 0);
182
+ ascii8bit = rb_const_get(rb_cEncoding, rb_intern("ASCII_8BIT"));
183
+ encoding = rb_funcall(local_string, rb_intern("encoding"), 0);
184
+
185
+ if (ascii8bit == encoding && ascii8bit == default_external)
186
+ {
187
+ return local_string; //don't know default encoding
188
+ }
189
+ else if (encoding == ascii8bit)
190
+ {
191
+ local_string = rb_funcall(local_string, rb_intern("force_encoding"), 1, default_external);
192
+ }
193
+ return rb_funcall(local_string, rb_intern("encode"), 1, rb_str_new2("utf-8"));
194
+ #endif
195
+ }
196
+
197
+ VALUE exticonv_utf8_to_local(VALUE utf8_string)
198
+ {
199
+ #if RJB_RUBY_VERSION_CODE < 190
200
+ check_kcode();
201
+ if(RTEST(objIconvR2J))
202
+ {
203
+ return rb_funcall(objIconvJ2R, rb_intern("iconv"), 1, utf8_string);
204
+ }
205
+ else
206
+ {
207
+ return utf8_string;
208
+ }
209
+ #else
210
+ VALUE rb_cEncoding, encoding, ascii8bit;
211
+ rb_cEncoding = rb_const_get(rb_cObject, rb_intern("Encoding"));
212
+ encoding = rb_funcall(rb_cEncoding, rb_intern("default_external"), 0);
213
+ ascii8bit = rb_const_get(rb_cEncoding, rb_intern("ASCII_8BIT"));
214
+
215
+ utf8_string = rb_funcall(utf8_string, rb_intern("force_encoding"), 1, rb_str_new2("utf-8"));
216
+ if (ascii8bit == encoding)
217
+ {
218
+ return utf8_string; //don't know default encoding
219
+ }
220
+ else
221
+ {
222
+ return rb_funcall(utf8_string, rb_intern("encode"), 1, encoding);
223
+ }
224
+ #endif
225
+ }
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Rjb - Ruby <-> Java Bridge
3
+ * Copyright(c) 2004 Kuwashima
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * $Id: riconv.h 43 2007-12-26 18:55:04Z kuwa1 $
16
+ */
17
+ #ifndef _RICONV_H
18
+ #define _RICONV_H
19
+
20
+
21
+ VALUE exticonv_local_to_utf8(VALUE);
22
+ VALUE exticonv_utf8_to_local(VALUE);
23
+
24
+ #endif /* _RICONV_H */
@@ -0,0 +1,2807 @@
1
+ /*
2
+ * Rjb - Ruby <-> Java Bridge
3
+ * Copyright(c) 2004,2005,2006,2007 arton
4
+ *
5
+ * This library is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * This library is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * $Id: rjb.c 50 2007-12-28 07:31:33Z arton $
16
+ */
17
+
18
+ #define RJB_VERSION "1.1.0"
19
+
20
+ #include "ruby.h"
21
+ #include "extconf.h"
22
+ #if RJB_RUBY_VERSION_CODE < 190
23
+ #include "st.h"
24
+ #else
25
+ #include "ruby/st.h"
26
+ #endif
27
+ #include "jniwrap.h"
28
+ #include "jp_co_infoseek_hp_arton_rjb_RBridge.h"
29
+ #include "riconv.h"
30
+ #include "rjb.h"
31
+
32
+ /*
33
+ * Method Modifier Flag defined in
34
+ * http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#88358
35
+ */
36
+ #define ACC_PUBLIC 0x0001
37
+ #define ACC_PRIVATE 0x0002
38
+ #define ACC_PROTECTED 0x0004
39
+ #define ACC_STATIC 0x0008
40
+ #define ACC_FINAL 0x0010
41
+ #define ACC_VOLATILE 0x0040
42
+ #define ACC_TRANSIENT 0x0080
43
+
44
+ static void register_class(VALUE, VALUE);
45
+ static VALUE import_class(JNIEnv* jenv, jclass, VALUE);
46
+ static VALUE register_instance(JNIEnv* jenv, struct jvi_data*, jobject);
47
+ static VALUE rjb_s_free(struct jv_data*);
48
+ static VALUE rjb_class_forname(int argc, VALUE* argv, VALUE self);
49
+ static void setup_metadata(JNIEnv* jenv, VALUE self, struct jv_data*, VALUE classname);
50
+ static VALUE jarray2rv(JNIEnv* jenv, jvalue val);
51
+ static jarray r2objarray(JNIEnv* jenv, VALUE v, const char* cls);
52
+ static VALUE jv2rv_withprim(JNIEnv* jenv, jobject o);
53
+ static J2R get_arrayconv(const char* cname, char* depth);
54
+
55
+ static VALUE rjb;
56
+ static VALUE jklass;
57
+ static VALUE rjbc;
58
+ static VALUE rjbi;
59
+ static VALUE rjbb;
60
+
61
+ VALUE rjb_loaded_classes;
62
+ static VALUE proxies;
63
+ JavaVM* rjb_jvm;
64
+ jclass rjb_rbridge;
65
+ jmethodID rjb_register_bridge;
66
+ static JNIEnv* main_jenv;
67
+ static VALUE primitive_conversion = Qfalse;
68
+
69
+ /*
70
+ * Object cache, never destroyed
71
+ */
72
+ /* method */
73
+ static jmethodID method_getModifiers;
74
+ static jmethodID method_getName;
75
+ static jmethodID getParameterTypes;
76
+ static jmethodID getReturnType;
77
+ /* field */
78
+ static jmethodID field_getModifiers;
79
+ static jmethodID field_getName;
80
+ static jmethodID field_getType;
81
+ /* constructor */
82
+ static jmethodID ctrGetParameterTypes;
83
+ /* class */
84
+ static jclass j_class;
85
+ jmethodID rjb_class_getName;
86
+ /* throwable */
87
+ jclass rjb_j_throwable;
88
+ jmethodID rjb_throwable_getMessage;
89
+ /* String global reference */
90
+ static jclass j_string;
91
+ static jmethodID str_tostring;
92
+ /* Object global reference */
93
+ static jclass j_object;
94
+
95
+ enum PrimitiveType {
96
+ PRM_INT = 0,
97
+ PRM_LONG,
98
+ PRM_DOUBLE,
99
+ PRM_BOOLEAN,
100
+ PRM_CHARACTER,
101
+ PRM_SHORT,
102
+ PRM_BYTE,
103
+ PRM_FLOAT,
104
+ //
105
+ PRM_LAST
106
+ };
107
+
108
+ /*
109
+ * Native type conversion table
110
+ */
111
+ typedef struct jobject_ruby_table {
112
+ const char* classname;
113
+ const char* to_prim_method;
114
+ const char* prmsig;
115
+ const char* ctrsig;
116
+ jclass klass; /* primitive class */
117
+ jmethodID to_prim_id;
118
+ jmethodID ctr_id;
119
+ J2R func;
120
+ } jprimitive_table;
121
+
122
+ JNIEnv* rjb_attach_current_thread(void)
123
+ {
124
+ JNIEnv* env;
125
+ (*rjb_jvm)->AttachCurrentThread(rjb_jvm, (void**)&env, '\0');
126
+ return env;
127
+ }
128
+
129
+
130
+ void rjb_release_string(JNIEnv *jenv, jstring str, const char* chrs)
131
+ {
132
+ (*jenv)->ReleaseStringUTFChars(jenv, str, chrs);
133
+ (*jenv)->DeleteLocalRef(jenv, str);
134
+ }
135
+
136
+ static char* java2jniname(char* jnicls)
137
+ {
138
+ char* p;
139
+ for (p = jnicls; *p; p++)
140
+ {
141
+ if (*p == '.')
142
+ {
143
+ *p = '/';
144
+ }
145
+ }
146
+ return jnicls;
147
+ }
148
+
149
+ static char* jni2javaname(char* jnicls)
150
+ {
151
+ char* p;
152
+ for (p = jnicls; *p; p++)
153
+ {
154
+ if (*p == '/')
155
+ {
156
+ *p = '.';
157
+ }
158
+ }
159
+ return jnicls;
160
+ }
161
+
162
+ static char* next_sig(char* p)
163
+ {
164
+ if (!*p)
165
+ {
166
+ return p;
167
+ }
168
+ if (*p == '[')
169
+ {
170
+ p++;
171
+ }
172
+ if (*p == 'L')
173
+ {
174
+ while (*p && *p != ';')
175
+ {
176
+ p++;
177
+ }
178
+ }
179
+ return (*p) ? ++p : p;
180
+ }
181
+
182
+ static VALUE jstring2val(JNIEnv* jenv, jstring s)
183
+ {
184
+ const char* p;
185
+ VALUE v;
186
+
187
+ if (s == NULL)
188
+ {
189
+ return Qnil;
190
+ }
191
+ p = (*jenv)->GetStringUTFChars(jenv, s, NULL);
192
+ v = rb_str_new2(p);
193
+ v = exticonv_utf8_to_local(v);
194
+ rjb_release_string(jenv, s, p);
195
+ return v;
196
+ }
197
+
198
+ /*
199
+ * Type conversion tables
200
+ */
201
+ typedef struct type_conversion_table {
202
+ const char* jtype;
203
+ const char* jntype;
204
+ R2J r2j;
205
+ J2R j2r;
206
+ J2R ja2r;
207
+ R2JARRAY r2ja;
208
+ off_t jcall; /* for instance method */
209
+ off_t jscall; /* for static method */
210
+ } jconv_table;
211
+
212
+ /*
213
+ * conversion methods
214
+ * val will be released in this function.
215
+ */
216
+ static VALUE jv2rclass(JNIEnv* jenv, jclass jc)
217
+ {
218
+ const char* cname;
219
+ VALUE clsname;
220
+ VALUE v;
221
+ jstring nm = (*jenv)->CallObjectMethod(jenv, jc, rjb_class_getName);
222
+ rjb_check_exception(jenv, 0);
223
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
224
+ clsname = rb_str_new2(cname);
225
+ rjb_release_string(jenv, nm, cname);
226
+ v = rb_hash_aref(rjb_loaded_classes, clsname);
227
+ if (v == Qnil)
228
+ {
229
+ v = import_class(jenv, jc, clsname);
230
+ }
231
+ (*jenv)->DeleteLocalRef(jenv, jc);
232
+ return v;
233
+ }
234
+
235
+ static VALUE jv2rv_r(JNIEnv* jenv, jvalue val)
236
+ {
237
+ const char* cname;
238
+ jstring nm;
239
+ jclass klass;
240
+ VALUE clsname;
241
+ VALUE v;
242
+ struct jv_data* ptr;
243
+ // object to ruby
244
+ if (!val.l) return Qnil;
245
+ klass = (*jenv)->GetObjectClass(jenv, val.l);
246
+
247
+ if ((*jenv)->IsSameObject(jenv, klass, j_class))
248
+ {
249
+ (*jenv)->DeleteLocalRef(jenv, klass);
250
+ return jv2rclass(jenv, val.l);
251
+ }
252
+ nm = (*jenv)->CallObjectMethod(jenv, klass, rjb_class_getName);
253
+ rjb_check_exception(jenv, 0);
254
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
255
+ if (*cname == '[')
256
+ {
257
+ char depth = 0;
258
+ J2R j2r = get_arrayconv(cname, &depth);
259
+ rjb_release_string(jenv, nm, cname);
260
+ v = j2r(jenv, val);
261
+ (*jenv)->DeleteLocalRef(jenv, klass);
262
+ (*jenv)->DeleteLocalRef(jenv, val.l);
263
+ return v;
264
+ }
265
+ clsname = rb_str_new2(cname);
266
+ rjb_release_string(jenv, nm, cname);
267
+ v = rb_hash_aref(rjb_loaded_classes, clsname);
268
+ if (v == Qnil)
269
+ {
270
+ v = import_class(jenv, klass, clsname);
271
+ }
272
+ Data_Get_Struct(v, struct jv_data, ptr);
273
+ v = register_instance(jenv, (struct jvi_data*)ptr, val.l);
274
+ (*jenv)->DeleteLocalRef(jenv, klass);
275
+ (*jenv)->DeleteLocalRef(jenv, val.l);
276
+ return v;
277
+ }
278
+
279
+ static VALUE jv2rv(JNIEnv* jenv, jvalue val)
280
+ {
281
+ if (RTEST(primitive_conversion))
282
+ {
283
+ return jv2rv_withprim(jenv, val.l);
284
+ }
285
+ return jv2rv_r(jenv, val);
286
+ }
287
+
288
+ static VALUE jvoid2rv(JNIEnv* jenv, jvalue val)
289
+ {
290
+ return Qnil;
291
+ }
292
+
293
+ static VALUE jbyte2rv(JNIEnv* jenv, jvalue val)
294
+ {
295
+ return INT2NUM(val.b);
296
+ }
297
+
298
+ static VALUE jchar2rv(JNIEnv* jenv, jvalue val)
299
+ {
300
+ return INT2NUM(val.c);
301
+ }
302
+
303
+ static VALUE jdouble2rv(JNIEnv* jenv, jvalue val)
304
+ {
305
+ return rb_float_new(val.d);
306
+ }
307
+
308
+ static VALUE jfloat2rv(JNIEnv* jenv, jvalue val)
309
+ {
310
+ return rb_float_new((double)val.f);
311
+ }
312
+
313
+ static VALUE jint2rv(JNIEnv* jenv, jvalue val)
314
+ {
315
+ return INT2NUM(val.i);
316
+ }
317
+
318
+ static VALUE jlong2rv(JNIEnv* jenv, jvalue val)
319
+ {
320
+ #if HAVE_LONG_LONG
321
+ return LL2NUM(val.j);
322
+ #else
323
+ char bignum[64];
324
+ sprintf(bignum, "%ld * 0x100000000 + 0x%lx",
325
+ (long)(val.j >> 32), (unsigned long)val.j);
326
+ return rb_eval_string(bignum);
327
+ #endif
328
+ }
329
+
330
+ static VALUE jshort2rv(JNIEnv* jenv, jvalue val)
331
+ {
332
+ return INT2NUM(val.s);
333
+ }
334
+
335
+ static VALUE jboolean2rv(JNIEnv* jenv, jvalue val)
336
+ {
337
+ return (val.z) ? Qtrue : Qfalse;
338
+ }
339
+
340
+ static VALUE jstring2rv(JNIEnv* jenv, jvalue val)
341
+ {
342
+ return jstring2val(jenv, (jstring)val.l);
343
+ }
344
+
345
+ static VALUE ja2r(J2R conv, JNIEnv* jenv, jvalue val, int depth)
346
+ {
347
+ jsize len;
348
+ VALUE v;
349
+ int i;
350
+ if (!val.l) return Qnil;
351
+ if (depth == 1)
352
+ {
353
+ return conv(jenv, val);
354
+ }
355
+ len = (*jenv)->GetArrayLength(jenv, val.l);
356
+ v = rb_ary_new2(len);
357
+ for (i = 0; i < len; i++)
358
+ {
359
+ jvalue wrap;
360
+ wrap.l = (*jenv)->GetObjectArrayElement(jenv, val.l, i);
361
+ rb_ary_push(v, ja2r(conv, jenv, wrap, depth - 1));
362
+ }
363
+ (*jenv)->DeleteLocalRef(jenv, val.l);
364
+ return v;
365
+ }
366
+
367
+ static VALUE jarray2rv(JNIEnv* jenv, jvalue val)
368
+ {
369
+ jsize len;
370
+ VALUE v;
371
+ int i;
372
+ if (!val.l) return Qnil;
373
+ len = (*jenv)->GetArrayLength(jenv, val.l);
374
+ v = rb_ary_new2(len);
375
+ for (i = 0; i < len; i++)
376
+ {
377
+ jvalue wrap;
378
+ wrap.l = (*jenv)->GetObjectArrayElement(jenv, val.l, i);
379
+ /* wrap.l will be release in jv2rv */
380
+ rb_ary_push(v, jv2rv(jenv, wrap));
381
+ }
382
+ (*jenv)->DeleteLocalRef(jenv, val.l);
383
+ return v;
384
+ }
385
+
386
+ static VALUE ca2rv(JNIEnv* jenv, void* p)
387
+ {
388
+ return INT2FIX(*(jchar*)p);
389
+ }
390
+
391
+ static VALUE da2rv(JNIEnv* jenv, void* p)
392
+ {
393
+ return rb_float_new(*(jdouble*)p);
394
+ }
395
+
396
+ static VALUE fa2rv(JNIEnv* jenv, void* p)
397
+ {
398
+ return rb_float_new(*(jfloat*)p);
399
+ }
400
+
401
+ static VALUE ia2rv(JNIEnv* jenv, void* p)
402
+ {
403
+ return INT2NUM(*(jint*)p);
404
+ }
405
+
406
+ static VALUE la2rv(JNIEnv* jenv, void* p)
407
+ {
408
+ #if HAVE_LONG_LONG
409
+ return LL2NUM(*(jlong*)p);
410
+ #else
411
+ return LONG2NUM(*(jlong*)p);
412
+ #endif
413
+ }
414
+
415
+ static VALUE sa2rv(JNIEnv* jenv, void* p)
416
+ {
417
+ return INT2FIX(*(jshort*)p);
418
+ }
419
+
420
+ static VALUE ba2rv(JNIEnv* jenv, void* p)
421
+ {
422
+ return (*(jboolean*)p) ? Qtrue : Qfalse;
423
+ }
424
+
425
+ /*
426
+ * val : released in this function.
427
+ */
428
+ static VALUE call_conv(JNIEnv* jenv, jvalue val, size_t sz, void* p, CONV conv, size_t fnc)
429
+ {
430
+ int i;
431
+ char* cp = (char*)p;
432
+ jsize len = (*jenv)->GetArrayLength(jenv, val.l);
433
+ VALUE v = rb_ary_new2(len);
434
+ VALUE* pv = RARRAY_PTR(v);
435
+ RARRAY_LEN(v) = len;
436
+ for (i = 0; i < len; i++)
437
+ {
438
+ *pv++ =conv(jenv, cp);
439
+ cp += sz;
440
+ }
441
+ (*(RELEASEARRAY*)(((char*)*jenv) + fnc))(jenv, val.l, p, JNI_ABORT);
442
+ (*jenv)->DeleteLocalRef(jenv, val.l);
443
+ return v;
444
+ }
445
+
446
+ static VALUE jbytearray2rv(JNIEnv* jenv, jvalue val)
447
+ {
448
+ jsize len = (*jenv)->GetArrayLength(jenv, val.l);
449
+ jbyte* p = (*jenv)->GetByteArrayElements(jenv, val.l, NULL);
450
+ VALUE v = rb_str_new((char*)p, len);
451
+ (*jenv)->ReleaseByteArrayElements(jenv, val.l, p, JNI_ABORT);
452
+ (*jenv)->DeleteLocalRef(jenv, val.l);
453
+ return v;
454
+ }
455
+ static VALUE jchararray2rv(JNIEnv* jenv, jvalue val)
456
+ {
457
+ jchar* p = (*jenv)->GetCharArrayElements(jenv, val.l, NULL);
458
+ return call_conv(jenv, val, sizeof(jchar), p, ca2rv,
459
+ offsetof(struct JNINativeInterface_, ReleaseCharArrayElements));
460
+ }
461
+ static VALUE jdoublearray2rv(JNIEnv* jenv, jvalue val)
462
+ {
463
+ jdouble* p = (*jenv)->GetDoubleArrayElements(jenv, val.l, NULL);
464
+ return call_conv(jenv, val, sizeof(jdouble), p, da2rv,
465
+ offsetof(struct JNINativeInterface_, ReleaseDoubleArrayElements));
466
+ }
467
+ static VALUE jfloatarray2rv(JNIEnv* jenv, jvalue val)
468
+ {
469
+ jfloat* p = (*jenv)->GetFloatArrayElements(jenv, val.l, NULL);
470
+ return call_conv(jenv, val, sizeof(jfloat), p, fa2rv,
471
+ offsetof(struct JNINativeInterface_, ReleaseFloatArrayElements));
472
+ }
473
+ static VALUE jintarray2rv(JNIEnv* jenv, jvalue val)
474
+ {
475
+ jint* p = (*jenv)->GetIntArrayElements(jenv, val.l, NULL);
476
+ return call_conv(jenv, val, sizeof(jint), p, ia2rv,
477
+ offsetof(struct JNINativeInterface_, ReleaseIntArrayElements));
478
+ }
479
+ static VALUE jlongarray2rv(JNIEnv* jenv, jvalue val)
480
+ {
481
+ jlong* p = (*jenv)->GetLongArrayElements(jenv, val.l, NULL);
482
+ return call_conv(jenv, val, sizeof(jlong), p, la2rv,
483
+ offsetof(struct JNINativeInterface_, ReleaseLongArrayElements));
484
+ }
485
+ static VALUE jshortarray2rv(JNIEnv* jenv, jvalue val)
486
+ {
487
+ jshort* p = (*jenv)->GetShortArrayElements(jenv, val.l, NULL);
488
+ return call_conv(jenv, val, sizeof(jshort), p, sa2rv,
489
+ offsetof(struct JNINativeInterface_, ReleaseShortArrayElements));
490
+ }
491
+ static VALUE jstringarray2rv(JNIEnv* jenv, jvalue val)
492
+ {
493
+ int i;
494
+ jsize len = (*jenv)->GetArrayLength(jenv, val.l);
495
+ VALUE v = rb_ary_new2(len);
496
+ for (i = 0; i < len; i++)
497
+ {
498
+ jobject p = (*jenv)->GetObjectArrayElement(jenv, val.l, i);
499
+ rb_ary_push(v, jstring2val(jenv, (jstring)p));
500
+ }
501
+ (*jenv)->DeleteLocalRef(jenv, val.l);
502
+ return v;
503
+ }
504
+ static VALUE jbooleanarray2rv(JNIEnv* jenv, jvalue val)
505
+ {
506
+ jboolean* p = (*jenv)->GetBooleanArrayElements(jenv, val.l, NULL);
507
+ return call_conv(jenv, val, sizeof(jboolean), p, ba2rv,
508
+ offsetof(struct JNINativeInterface_, ReleaseBooleanArrayElements));
509
+ }
510
+
511
+ /*
512
+ * table that handles java primitive type.
513
+ * index: according to enum PrimitiveType.
514
+ */
515
+ static jprimitive_table jpcvt[] = {
516
+ { "java/lang/Integer", "intValue", "()I", "(I)V", NULL, 0, 0, jint2rv, },
517
+ { "java/lang/Long", "longValue", "()J", "(J)V", NULL, 0, 0, jlong2rv, },
518
+ { "java/lang/Double", "doubleValue", "()D", "(D)V", NULL, 0, 0, jdouble2rv, },
519
+ { "java/lang/Boolean", "booleanValue", "()Z", "(Z)Ljava/lang/Boolean;",
520
+ NULL, 0, 0, jboolean2rv, },
521
+ { "java/lang/Character", "charValue", "()C", NULL, NULL, 0, 0, jint2rv, },
522
+ { "java/lang/Short", "intValue", "()I", NULL, NULL, 0, 0, jint2rv, },
523
+ { "java/lang/Byte", "intValue", "()I", NULL, NULL, 0, 0, jint2rv, },
524
+ { "java/lang/Float", "doubleValue", "()D", NULL, NULL, 0, 0, jdouble2rv, },
525
+ };
526
+
527
+ /*
528
+ * o will be released in this function.
529
+ */
530
+ static VALUE jv2rv_withprim(JNIEnv* jenv, jobject o)
531
+ {
532
+ jvalue jv;
533
+ int i;
534
+ jclass klass;
535
+ jv.j = 0;
536
+ if (!o)
537
+ rb_raise(rb_eRuntimeError, "Object is NULL");
538
+ klass = (*jenv)->GetObjectClass(jenv, o);
539
+ for (i = PRM_INT; i < PRM_LAST; i++)
540
+ {
541
+ if ((*jenv)->IsSameObject(jenv, jpcvt[i].klass, klass))
542
+ {
543
+ switch (*(jpcvt[i].to_prim_method))
544
+ {
545
+ case 'i':
546
+ jv.i = (*jenv)->CallIntMethod(jenv, o, jpcvt[i].to_prim_id);
547
+ break;
548
+ case 'b':
549
+ jv.z = (*jenv)->CallBooleanMethod(jenv, o, jpcvt[i].to_prim_id);
550
+ break;
551
+ case 'd':
552
+ jv.d = (*jenv)->CallDoubleMethod(jenv, o, jpcvt[i].to_prim_id);
553
+ break;
554
+ case 'c':
555
+ jv.c = (*jenv)->CallCharMethod(jenv, o, jpcvt[i].to_prim_id);
556
+ break;
557
+ case 'l':
558
+ jv.j = (*jenv)->CallLongMethod(jenv, o, jpcvt[i].to_prim_id);
559
+ break;
560
+ default:
561
+ rb_raise(rb_eRuntimeError, "no convertor defined(%d)", i);
562
+ break;
563
+ }
564
+ (*jenv)->DeleteLocalRef(jenv, o);
565
+ return jpcvt[i].func(jenv, jv);
566
+ }
567
+ }
568
+ if ((*jenv)->IsSameObject(jenv, j_string, klass))
569
+ {
570
+ return jstring2val(jenv, o);
571
+ }
572
+ jv.l = o;
573
+ return jv2rv_r(jenv, jv);
574
+ }
575
+
576
+ /*
577
+ * functions convert VALUE to jvalue
578
+ */
579
+ static void rv2jv(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
580
+ {
581
+ jv->l = NULL;
582
+ }
583
+
584
+ static void rv2jbyte(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
585
+ {
586
+ if (!release)
587
+ jv->b = (jbyte)NUM2INT(val);
588
+ }
589
+ static void rv2jchar(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
590
+ {
591
+ if (!release)
592
+ jv->c = (jchar)NUM2INT(val);
593
+ }
594
+ static void rv2jdouble(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
595
+ {
596
+ if (release) return;
597
+ switch (TYPE(val))
598
+ {
599
+ case T_FIXNUM:
600
+ jv->d = NUM2INT(val);
601
+ break;
602
+ case T_FLOAT:
603
+ jv->d = NUM2DBL(val);
604
+ break;
605
+ default:
606
+ rb_raise(rb_eRuntimeError, "can't change to double");
607
+ break;
608
+ }
609
+ }
610
+ static void rv2jfloat(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
611
+ {
612
+ if (release) return;
613
+ switch (TYPE(val))
614
+ {
615
+ case T_FIXNUM:
616
+ jv->f = (float)NUM2INT(val);
617
+ break;
618
+ case T_FLOAT:
619
+ jv->f = (float)NUM2DBL(val);
620
+ break;
621
+ default:
622
+ rb_raise(rb_eRuntimeError, "can't change to float");
623
+ break;
624
+ }
625
+ }
626
+ static void rv2jint(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
627
+ {
628
+ if (!release)
629
+ jv->i = NUM2INT(val);
630
+ }
631
+ static void rv2jlong(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
632
+ {
633
+ if (release) return;
634
+ switch (TYPE(val))
635
+ {
636
+ case T_FIXNUM:
637
+ jv->j = NUM2INT(val);
638
+ break;
639
+ default:
640
+ #if HAVE_LONG_LONG
641
+ jv->j = NUM2LL(val);
642
+ #else
643
+ rb_raise(rb_eRuntimeError, "can't change to long");
644
+ #endif
645
+ break;
646
+ }
647
+ }
648
+ static void rv2jshort(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
649
+ {
650
+ if (!release)
651
+ jv->s = (short)NUM2INT(val);
652
+ }
653
+ static void rv2jboolean(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
654
+ {
655
+ if (!release)
656
+ jv->z = (RTEST(val)) ? JNI_TRUE : JNI_FALSE;
657
+ }
658
+ static void rv2jstring(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
659
+ {
660
+ if (!release)
661
+ {
662
+ if (TYPE(val) == T_DATA
663
+ && (RBASIC(val)->klass == rjbi || RBASIC(val)->klass == rjb))
664
+ {
665
+ struct jvi_data* ptr;
666
+ Data_Get_Struct(val, struct jvi_data, ptr);
667
+ if ((*jenv)->IsInstanceOf(jenv, ptr->obj, j_string))
668
+ {
669
+ jv->l = ptr->obj;
670
+ }
671
+ else
672
+ {
673
+ jmethodID tostr;
674
+ jstring js;
675
+ tostr = (*jenv)->GetMethodID(jenv, ptr->klass, "toString", "()Ljava/lang/String;");
676
+ rjb_check_exception(jenv, 0);
677
+ js = (*jenv)->CallObjectMethod(jenv, ptr->obj, tostr);
678
+ rjb_check_exception(jenv, 0);
679
+ jv->l = js;
680
+ }
681
+ }
682
+ else
683
+ {
684
+ if (NIL_P(val))
685
+ {
686
+ jv->l = NULL;
687
+ }
688
+ else
689
+ {
690
+ val = exticonv_local_to_utf8(val);
691
+ jv->l = (*jenv)->NewStringUTF(jenv, StringValuePtr(val));
692
+ }
693
+ }
694
+ }
695
+ else
696
+ {
697
+ if (TYPE(val) == T_DATA)
698
+ {
699
+ if (RBASIC(val)->klass == rjbi || RBASIC(val)->klass == rjb)
700
+ {
701
+ struct jvi_data* ptr;
702
+ Data_Get_Struct(val, struct jvi_data, ptr);
703
+ if ((*jenv)->IsInstanceOf(jenv, ptr->obj, j_string))
704
+ {
705
+ return; // never delete at this time
706
+ }
707
+ }
708
+ }
709
+ (*jenv)->DeleteLocalRef(jenv, jv->l);
710
+ }
711
+ }
712
+
713
+ /*
714
+ * psig may be NULL (from proxy/array call)
715
+ */
716
+ static void rv2jobject(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
717
+ {
718
+ if (!release)
719
+ {
720
+ jv->l = NULL;
721
+ if (val == Qtrue || val == Qfalse)
722
+ {
723
+ jv->l = (*jenv)->CallStaticObjectMethod(jenv,
724
+ jpcvt[PRM_BOOLEAN].klass, jpcvt[PRM_BOOLEAN].ctr_id,
725
+ (val == Qtrue) ? JNI_TRUE : JNI_FALSE);
726
+ }
727
+ else if (NIL_P(val))
728
+ {
729
+ // no-op
730
+ }
731
+ else if (FIXNUM_P(val))
732
+ {
733
+ jvalue arg;
734
+ int idx = PRM_INT;
735
+ #if HAVE_LONG_LONG
736
+ arg.j = FIX2LONG(val);
737
+ if (arg.j < INT_MIN || arg.j > INT_MAX)
738
+ {
739
+ idx = PRM_LONG;
740
+ }
741
+ #else
742
+ arg.i = FIX2LONG(val);
743
+ #endif
744
+ jv->l = (*jenv)->NewObject(jenv, jpcvt[idx].klass,
745
+ jpcvt[idx].ctr_id, arg);
746
+ }
747
+ else
748
+ {
749
+ jvalue arg;
750
+ switch (TYPE(val))
751
+ {
752
+ case T_DATA:
753
+ if (RBASIC(val)->klass == rjbi || RBASIC(val)->klass == rjb)
754
+ {
755
+ // TODO: check instanceof (class (in psig) )
756
+ struct jvi_data* ptr;
757
+ Data_Get_Struct(val, struct jvi_data, ptr);
758
+ jv->l = ptr->obj;
759
+ }
760
+ else if (RBASIC(val)->klass == rjbb)
761
+ {
762
+ struct rj_bridge* ptr;
763
+ Data_Get_Struct(val, struct rj_bridge, ptr);
764
+ jv->l = ptr->proxy;
765
+ }
766
+ else if (rb_class_inherited(rjbc, RBASIC(val)->klass))
767
+ {
768
+ struct jv_data* ptr;
769
+ Data_Get_Struct(val, struct jv_data, ptr);
770
+ jv->l = ptr->idata.obj;
771
+ }
772
+ break;
773
+ case T_STRING:
774
+ rv2jstring(jenv, val, jv, NULL, 0);
775
+ break;
776
+ case T_FLOAT:
777
+ arg.d = NUM2DBL(val);
778
+ jv->l = (*jenv)->NewObject(jenv, jpcvt[PRM_DOUBLE].klass,
779
+ jpcvt[PRM_DOUBLE].ctr_id, arg.d);
780
+ break;
781
+ case T_ARRAY:
782
+ jv->l = r2objarray(jenv, val, "Ljava/lang/Object;");
783
+ break;
784
+ #if HAVE_LONG_LONG
785
+ case T_BIGNUM:
786
+ arg.j = rb_big2ll(val);
787
+ jv->l = (*jenv)->NewObject(jenv, jpcvt[PRM_LONG].klass,
788
+ jpcvt[PRM_LONG].ctr_id, arg);
789
+ break;
790
+ #endif
791
+ default:
792
+ rb_raise(rb_eRuntimeError, "can't convert to java type");
793
+ break;
794
+ }
795
+ }
796
+ }
797
+ else
798
+ {
799
+ switch (TYPE(val))
800
+ {
801
+ case T_STRING:
802
+ case T_FLOAT:
803
+ case T_ARRAY:
804
+ case T_BIGNUM:
805
+ if (jv->l) (*jenv)->DeleteLocalRef(jenv, jv->l);
806
+ break;
807
+ }
808
+ }
809
+ }
810
+
811
+ static void check_fixnumarray(VALUE v)
812
+ {
813
+ int i;
814
+ int len = RARRAY_LEN(v);
815
+ VALUE* p = RARRAY_PTR(v);
816
+ // check all fixnum (overflow is permit)
817
+ for (i = 0; i < len; i++)
818
+ {
819
+ if (!FIXNUM_P(*p++))
820
+ {
821
+ rb_raise(rb_eRuntimeError, "array element must be a fixnum");
822
+ }
823
+ }
824
+ }
825
+
826
+ static jarray r2barray(JNIEnv* jenv, VALUE v, const char* cls)
827
+ {
828
+ jarray ary = NULL;
829
+ if (TYPE(v) == T_STRING)
830
+ {
831
+ ary = (*jenv)->NewByteArray(jenv, RSTRING_LEN(v));
832
+ (*jenv)->SetByteArrayRegion(jenv, ary, 0, RSTRING_LEN(v),
833
+ RSTRING_PTR(v));
834
+ }
835
+ else if (TYPE(v) == T_ARRAY)
836
+ {
837
+ int i;
838
+ jbyte* pb;
839
+ check_fixnumarray(v);
840
+ ary = (*jenv)->NewByteArray(jenv, RARRAY_LEN(v));
841
+ pb = (*jenv)->GetByteArrayElements(jenv, ary, NULL);
842
+ for (i = 0; i < RARRAY_LEN(v); i++)
843
+ {
844
+ *(pb + i) = (jbyte)FIX2ULONG(RARRAY_PTR(v)[i]);
845
+ }
846
+ (*jenv)->ReleaseByteArrayElements(jenv, ary, pb, 0);
847
+ }
848
+ if (!ary)
849
+ {
850
+ rb_raise(rb_eRuntimeError, "can't coerce to byte array");
851
+ }
852
+ return ary;
853
+ }
854
+
855
+ static jarray r2carray(JNIEnv* jenv, VALUE v, const char* cls)
856
+ {
857
+ jarray ary = NULL;
858
+ if (TYPE(v) == T_ARRAY)
859
+ {
860
+ int i;
861
+ jchar* pb;
862
+ check_fixnumarray(v);
863
+ ary = (*jenv)->NewCharArray(jenv, RARRAY_LEN(v));
864
+ pb = (*jenv)->GetCharArrayElements(jenv, ary, NULL);
865
+ for (i = 0; i < RARRAY_LEN(v); i++)
866
+ {
867
+ *(pb + i) = (jchar)FIX2ULONG(RARRAY_PTR(v)[i]);
868
+ }
869
+ (*jenv)->ReleaseCharArrayElements(jenv, ary, pb, 0);
870
+ return ary;
871
+ }
872
+ rb_raise(rb_eRuntimeError, "can't coerce to char array");
873
+ }
874
+
875
+ static jarray r2darray(JNIEnv* jenv, VALUE v, const char* cls)
876
+ {
877
+ jarray ary = NULL;
878
+ if (TYPE(v) == T_ARRAY)
879
+ {
880
+ int i;
881
+ jdouble* pb;
882
+ ary = (*jenv)->NewDoubleArray(jenv, RARRAY_LEN(v));
883
+ pb = (*jenv)->GetDoubleArrayElements(jenv, ary, NULL);
884
+ for (i = 0; i < RARRAY_LEN(v); i++)
885
+ {
886
+ *(pb + i) = (jdouble)rb_num2dbl(RARRAY_PTR(v)[i]);
887
+ }
888
+ (*jenv)->ReleaseDoubleArrayElements(jenv, ary, pb, 0);
889
+ return ary;
890
+ }
891
+ rb_raise(rb_eRuntimeError, "can't coerce to double array");
892
+ }
893
+
894
+ static jarray r2farray(JNIEnv* jenv, VALUE v, const char* cls)
895
+ {
896
+ jarray ary = NULL;
897
+ if (TYPE(v) == T_ARRAY)
898
+ {
899
+ int i;
900
+ jfloat* pb;
901
+ ary = (*jenv)->NewFloatArray(jenv, RARRAY_LEN(v));
902
+ pb = (*jenv)->GetFloatArrayElements(jenv, ary, NULL);
903
+ for (i = 0; i < RARRAY_LEN(v); i++)
904
+ {
905
+ *(pb + i) = (jfloat)rb_num2dbl(RARRAY_PTR(v)[i]);
906
+ }
907
+ (*jenv)->ReleaseFloatArrayElements(jenv, ary, pb, 0);
908
+ return ary;
909
+ }
910
+ rb_raise(rb_eRuntimeError, "can't coerce to float array");
911
+ }
912
+
913
+ static jarray r2iarray(JNIEnv* jenv, VALUE v, const char* cls)
914
+ {
915
+ jarray ary = NULL;
916
+ if (TYPE(v) == T_ARRAY)
917
+ {
918
+ int i;
919
+ jint* pb;
920
+ check_fixnumarray(v);
921
+ ary = (*jenv)->NewIntArray(jenv, RARRAY_LEN(v));
922
+ pb = (*jenv)->GetIntArrayElements(jenv, ary, NULL);
923
+ for (i = 0; i < RARRAY_LEN(v); i++)
924
+ {
925
+ *(pb + i) = (jint)FIX2LONG(RARRAY_PTR(v)[i]);
926
+ }
927
+ (*jenv)->ReleaseIntArrayElements(jenv, ary, pb, 0);
928
+ return ary;
929
+ }
930
+ rb_raise(rb_eRuntimeError, "can't coerce to int array");
931
+ }
932
+
933
+ static jarray r2larray(JNIEnv* jenv, VALUE v, const char* cls)
934
+ {
935
+ jarray ary = NULL;
936
+ if (TYPE(v) == T_ARRAY)
937
+ {
938
+ int i;
939
+ jlong* pb;
940
+ ary = (*jenv)->NewLongArray(jenv, RARRAY_LEN(v));
941
+ pb = (*jenv)->GetLongArrayElements(jenv, ary, NULL);
942
+ for (i = 0; i < RARRAY_LEN(v); i++)
943
+ {
944
+ #if HAVE_LONG_LONG
945
+ *(pb + i) = (jlong)rb_num2ll(RARRAY_PTR(v)[i]);
946
+ #else
947
+ *(pb + i) = (jlong)FIX2LONG(RARRAY_PTR(v)[i]);
948
+ #endif
949
+ }
950
+ (*jenv)->ReleaseLongArrayElements(jenv, ary, pb, 0);
951
+ return ary;
952
+ }
953
+ rb_raise(rb_eRuntimeError, "can't coerce to long array");
954
+ }
955
+
956
+ static jarray r2sarray(JNIEnv* jenv, VALUE v, const char* cls)
957
+ {
958
+ jarray ary = NULL;
959
+ if (TYPE(v) == T_ARRAY)
960
+ {
961
+ int i;
962
+ jshort* pb;
963
+ check_fixnumarray(v);
964
+ ary = (*jenv)->NewShortArray(jenv, RARRAY_LEN(v));
965
+ pb = (*jenv)->GetShortArrayElements(jenv, ary, NULL);
966
+ for (i = 0; i < RARRAY_LEN(v); i++)
967
+ {
968
+ *(pb + i) = (jshort)FIX2LONG(RARRAY_PTR(v)[i]);
969
+ }
970
+ (*jenv)->ReleaseShortArrayElements(jenv, ary, pb, 0);
971
+ return ary;
972
+ }
973
+ rb_raise(rb_eRuntimeError, "can't coerce to short array");
974
+ }
975
+
976
+ static jarray r2boolarray(JNIEnv* jenv, VALUE v, const char* cls)
977
+ {
978
+ jarray ary = NULL;
979
+ if (TYPE(v) == T_ARRAY)
980
+ {
981
+ int i;
982
+ jboolean* pb;
983
+ ary = (*jenv)->NewBooleanArray(jenv, RARRAY_LEN(v));
984
+ pb = (*jenv)->GetBooleanArrayElements(jenv, ary, NULL);
985
+ for (i = 0; i < RARRAY_LEN(v); i++)
986
+ {
987
+ *(pb + i)
988
+ = (!RTEST(RARRAY_PTR(v)[i]))
989
+ ? JNI_FALSE : JNI_TRUE;
990
+ }
991
+ (*jenv)->ReleaseBooleanArrayElements(jenv, ary, pb, 0);
992
+ return ary;
993
+ }
994
+ rb_raise(rb_eRuntimeError, "can't coerce to boolean array");
995
+ }
996
+
997
+ static jarray r2voidarray(JNIEnv* jenv, VALUE v, const char* cls)
998
+ {
999
+ rb_raise(rb_eRuntimeError, "void never arrayed");
1000
+ }
1001
+
1002
+ static jarray r2objarray(JNIEnv* jenv, VALUE v, const char* cls)
1003
+ {
1004
+ jarray ary = NULL;
1005
+ if (TYPE(v) == T_ARRAY)
1006
+ {
1007
+ int i;
1008
+ ary = (*jenv)->NewObjectArray(jenv, RARRAY_LEN(v), j_object, NULL);
1009
+ rjb_check_exception(jenv, 0);
1010
+ for (i = 0; i < RARRAY_LEN(v); i++)
1011
+ {
1012
+ jvalue jv;
1013
+ rv2jobject(jenv, RARRAY_PTR(v)[i], &jv, NULL, 0);
1014
+ (*jenv)->SetObjectArrayElement(jenv, ary, i, jv.l);
1015
+ }
1016
+ return ary;
1017
+ }
1018
+ rb_raise(rb_eRuntimeError, "can't coerce to object array");
1019
+ }
1020
+
1021
+ /*
1022
+ * Type convertion tables
1023
+ */
1024
+ static const jconv_table jcvt[] = {
1025
+ { "byte", "B", rv2jbyte, jbyte2rv,
1026
+ jbytearray2rv, r2barray,
1027
+ offsetof(struct JNINativeInterface_, CallByteMethodA),
1028
+ offsetof(struct JNINativeInterface_, CallStaticByteMethodA), },
1029
+ { "char", "C", rv2jchar, jchar2rv,
1030
+ jchararray2rv, r2carray,
1031
+ offsetof(struct JNINativeInterface_, CallCharMethodA),
1032
+ offsetof(struct JNINativeInterface_, CallStaticCharMethodA), },
1033
+ { "double", "D", rv2jdouble, jdouble2rv,
1034
+ jdoublearray2rv, r2darray,
1035
+ offsetof(struct JNINativeInterface_, CallDoubleMethodA),
1036
+ offsetof(struct JNINativeInterface_, CallStaticDoubleMethodA), },
1037
+ { "float", "F", rv2jfloat, jfloat2rv,
1038
+ jfloatarray2rv, r2farray,
1039
+ offsetof(struct JNINativeInterface_, CallFloatMethodA),
1040
+ offsetof(struct JNINativeInterface_, CallStaticFloatMethodA), },
1041
+ { "int", "I", rv2jint, jint2rv,
1042
+ jintarray2rv, r2iarray,
1043
+ offsetof(struct JNINativeInterface_, CallIntMethodA),
1044
+ offsetof(struct JNINativeInterface_, CallStaticIntMethodA), },
1045
+ { "long", "J", rv2jlong, jlong2rv,
1046
+ jlongarray2rv, r2larray,
1047
+ offsetof(struct JNINativeInterface_, CallLongMethodA),
1048
+ offsetof(struct JNINativeInterface_, CallStaticLongMethodA), },
1049
+ { "short", "S", rv2jshort, jshort2rv,
1050
+ jshortarray2rv, r2sarray,
1051
+ offsetof(struct JNINativeInterface_, CallShortMethodA),
1052
+ offsetof(struct JNINativeInterface_, CallStaticShortMethodA), },
1053
+ { "boolean", "Z", rv2jboolean, jboolean2rv,
1054
+ jbooleanarray2rv, r2boolarray,
1055
+ offsetof(struct JNINativeInterface_, CallBooleanMethodA),
1056
+ offsetof(struct JNINativeInterface_, CallStaticBooleanMethodA), },
1057
+ { "void", "V", rv2jv, jvoid2rv,
1058
+ NULL, r2voidarray,
1059
+ offsetof(struct JNINativeInterface_, CallVoidMethodA),
1060
+ offsetof(struct JNINativeInterface_, CallStaticVoidMethodA), },
1061
+ { "java.lang.String", "Ljava.lang.String;", rv2jstring, jstring2rv,
1062
+ jstringarray2rv, r2objarray,
1063
+ offsetof(struct JNINativeInterface_, CallObjectMethodA),
1064
+ offsetof(struct JNINativeInterface_, CallStaticObjectMethodA), },
1065
+ };
1066
+
1067
+ static void rv2jarray(JNIEnv* jenv, VALUE val, jvalue* jv, const char* psig, int release)
1068
+ {
1069
+ if (*psig != '[')
1070
+ {
1071
+ rb_raise(rb_eRuntimeError, "argument signature not array");
1072
+ }
1073
+ if (release)
1074
+ {
1075
+ (*jenv)->DeleteLocalRef(jenv, jv->l);
1076
+ }
1077
+ else
1078
+ {
1079
+ int i;
1080
+ jarray ja = NULL;
1081
+ if (NIL_P(val))
1082
+ {
1083
+ // no-op, null for an array
1084
+ }
1085
+ else if (*(psig + 1) == '[')
1086
+ {
1087
+ if (TYPE(val) != T_ARRAY) {
1088
+ rb_raise(rb_eRuntimeError, "array's rank unmatch");
1089
+ }
1090
+ ja = (*jenv)->NewObjectArray(jenv, RARRAY_LEN(val), j_object, NULL);
1091
+ rjb_check_exception(jenv, 0);
1092
+ for (i = 0; i < RARRAY_LEN(val); i++)
1093
+ {
1094
+ jvalue jv;
1095
+ rv2jarray(jenv, RARRAY_PTR(val)[i], &jv, psig + 1, 0);
1096
+ (*jenv)->SetObjectArrayElement(jenv, ja, i, jv.l);
1097
+ }
1098
+ }
1099
+ else
1100
+ {
1101
+ R2JARRAY r2a = r2objarray;
1102
+ for (i = 0; i < COUNTOF(jcvt); i++)
1103
+ {
1104
+ if (*(psig + 1) == jcvt[i].jntype[0])
1105
+ {
1106
+ r2a = jcvt[i].r2ja;
1107
+ break;
1108
+ }
1109
+ }
1110
+ ja = r2a(jenv, val, psig + 1);
1111
+ }
1112
+ jv->l = ja;
1113
+ }
1114
+ }
1115
+
1116
+ /*
1117
+ */
1118
+ static R2J get_r2j(JNIEnv* jenv, jobject o, int* siglen, char* sigp)
1119
+ {
1120
+ int len, i;
1121
+ const char* cname;
1122
+ R2J result = NULL;
1123
+ jstring nm = (*jenv)->CallObjectMethod(jenv, o, rjb_class_getName);
1124
+ rjb_check_exception(jenv, 0);
1125
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1126
+ if (*cname == '[')
1127
+ {
1128
+ if (siglen)
1129
+ {
1130
+ len = strlen(cname);
1131
+ *siglen += len;
1132
+ strcpy(sigp, cname);
1133
+ }
1134
+ result = rv2jarray;
1135
+ }
1136
+ else
1137
+ {
1138
+ for (i = 0; i < COUNTOF(jcvt); i++)
1139
+ {
1140
+ if (!strcmp(cname, jcvt[i].jtype))
1141
+ {
1142
+ if (siglen)
1143
+ {
1144
+ *siglen += strlen(jcvt[i].jntype);
1145
+ strcpy(sigp, jcvt[i].jntype);
1146
+ }
1147
+ result = jcvt[i].r2j;
1148
+ break;
1149
+ }
1150
+ }
1151
+ if (!result)
1152
+ {
1153
+ if (siglen)
1154
+ {
1155
+ *siglen += sprintf(sigp, "L%s;", cname);
1156
+ }
1157
+ result = rv2jobject;
1158
+ }
1159
+ }
1160
+ rjb_release_string(jenv, nm, cname);
1161
+ return result;
1162
+ }
1163
+
1164
+ static J2R get_arrayconv(const char* cname, char* pdepth)
1165
+ {
1166
+ int i;
1167
+ int start;
1168
+ for (start = 1; *(cname + start) == '['; start++);
1169
+ *pdepth = (char)start;
1170
+ for (i = 0; i < COUNTOF(jcvt); i++)
1171
+ {
1172
+ if (*(cname + start) == jcvt[i].jntype[0])
1173
+ {
1174
+ if (jcvt[i].jntype[0] == 'L'
1175
+ && strncmp(cname + start, jcvt[i].jntype, strlen(jcvt[i].jntype)))
1176
+ {
1177
+ break;
1178
+ }
1179
+ return jcvt[i].ja2r;
1180
+ }
1181
+ }
1182
+ return jarray2rv;
1183
+ }
1184
+
1185
+ static J2R get_j2r(JNIEnv* jenv, jobject cls, char* psig, char* pdepth, char* ppsig, off_t* piv, int static_method)
1186
+ {
1187
+ int i;
1188
+ J2R result = NULL;
1189
+ const char* cname;
1190
+ const char* jname = NULL;
1191
+ jstring nm = (*jenv)->CallObjectMethod(jenv, cls, rjb_class_getName);
1192
+ rjb_check_exception(jenv, 0);
1193
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1194
+
1195
+ if (*cname == '[')
1196
+ {
1197
+ result = get_arrayconv(cname, pdepth);
1198
+ jname = cname;
1199
+ }
1200
+ else
1201
+ {
1202
+ for (i = 0; i < COUNTOF(jcvt); i++)
1203
+ {
1204
+ if (!strcmp(cname, jcvt[i].jtype))
1205
+ {
1206
+ result = jcvt[i].j2r;
1207
+ *piv = (static_method) ? jcvt[i].jscall : jcvt[i].jcall;
1208
+ if (jcvt[i].jntype[0] != 'L')
1209
+ {
1210
+ *psig = jcvt[i].jntype[0];
1211
+ }
1212
+ jname = jcvt[i].jntype;
1213
+ break;
1214
+ }
1215
+ }
1216
+ }
1217
+ if (ppsig)
1218
+ {
1219
+ if (!jname)
1220
+ {
1221
+ sprintf(ppsig, "L%s;", cname);
1222
+ }
1223
+ else
1224
+ {
1225
+ strcpy(ppsig, jname);
1226
+ }
1227
+ java2jniname(ppsig);
1228
+ }
1229
+ rjb_release_string(jenv, nm, cname);
1230
+ return result;
1231
+ }
1232
+
1233
+ static void setup_j2r(JNIEnv* jenv, jobject cls, struct cls_method* pm, int static_method)
1234
+ {
1235
+ off_t iv = 0;
1236
+ J2R result = get_j2r(jenv, cls, &pm->basic.result_signature, &pm->basic.result_arraydepth, NULL, &iv, static_method);
1237
+ pm->result_convert = (result) ? result : jv2rv;
1238
+ if (iv)
1239
+ {
1240
+ pm->method = iv;
1241
+ }
1242
+ else
1243
+ {
1244
+ pm->method = (static_method)
1245
+ ? offsetof(struct JNINativeInterface_, CallStaticObjectMethodA)
1246
+ : offsetof(struct JNINativeInterface_, CallObjectMethodA);
1247
+ }
1248
+ }
1249
+
1250
+ static void fill_convert(JNIEnv* jenv, struct cls_constructor* cls, jobjectArray tp, int count)
1251
+ {
1252
+ int i, siglen;
1253
+ R2J* tbl = ALLOC_N(R2J, count);
1254
+ char** sig = (char**)ALLOCA_N(char*, count);
1255
+ char siga[256];
1256
+ cls->arg_convert = tbl;
1257
+ memset(tbl, 0, sizeof(R2J) * count);
1258
+ siglen = 0;
1259
+ for (i = 0; i < count; i++)
1260
+ {
1261
+ jobject o = (*jenv)->GetObjectArrayElement(jenv, tp, i);
1262
+ *(tbl + i) = get_r2j(jenv, o, &siglen, siga);
1263
+ *(sig + i) = ALLOCA_N(char, strlen(siga) + 1);
1264
+ strcpy(*(sig + i), siga);
1265
+ }
1266
+ cls->method_signature = ALLOC_N(char, siglen + 1);
1267
+ *(cls->method_signature) = 0;
1268
+ for (i = 0; i < count; i++)
1269
+ {
1270
+ strcat(cls->method_signature, *(sig + i));
1271
+ }
1272
+ }
1273
+
1274
+ /*
1275
+ * create method info structure
1276
+ * m = instance of Method class
1277
+ * c = instance of the class
1278
+ */
1279
+ static void setup_methodbase(JNIEnv* jenv, struct cls_constructor* pm,
1280
+ jobjectArray parama, jsize pcount)
1281
+ {
1282
+ pm->arg_count = pcount;
1283
+ pm->method_signature = NULL;
1284
+ pm->result_signature = 'O';
1285
+ pm->result_arraydepth = 0;
1286
+ pm->arg_convert = NULL;
1287
+ if (pcount)
1288
+ {
1289
+ fill_convert(jenv, pm, parama, pcount);
1290
+ }
1291
+ }
1292
+
1293
+ static void register_methodinfo(struct cls_method* newpm, st_table* tbl)
1294
+ {
1295
+ struct cls_method* pm;
1296
+
1297
+ if (st_lookup(tbl, newpm->name, (st_data_t*)&pm))
1298
+ {
1299
+ newpm->next = pm->next;
1300
+ pm->next = newpm;
1301
+ }
1302
+ else
1303
+ {
1304
+ newpm->next = NULL;
1305
+ st_insert(tbl, newpm->name, (VALUE)newpm);
1306
+ }
1307
+ }
1308
+
1309
+ static struct cls_method* clone_methodinfo(struct cls_method* pm)
1310
+ {
1311
+ struct cls_method* result = ALLOC(struct cls_method);
1312
+ memcpy(result, pm, sizeof(struct cls_method));
1313
+ return result;
1314
+ }
1315
+
1316
+ static void make_alias(const char* jname, char* rname)
1317
+ {
1318
+ while (*jname)
1319
+ {
1320
+ if (isupper(*jname))
1321
+ {
1322
+ *rname++ = '_';
1323
+ *rname++ = tolower(*jname++);
1324
+ }
1325
+ else
1326
+ {
1327
+ *rname++ = *jname++;
1328
+ }
1329
+ }
1330
+ *rname = '\0';
1331
+ }
1332
+
1333
+ static void create_methodinfo(JNIEnv* jenv, st_table* tbl, jobject m, int static_method)
1334
+ {
1335
+ struct cls_method* result;
1336
+ struct cls_method* pm;
1337
+ char* param = NULL;
1338
+ const char* jname;
1339
+ jstring nm;
1340
+ jobjectArray parama;
1341
+ jobject cls;
1342
+ jsize param_count;
1343
+ char* rname;
1344
+
1345
+ result = ALLOC(struct cls_method);
1346
+ parama = (*jenv)->CallObjectMethod(jenv, m, getParameterTypes);
1347
+ rjb_check_exception(jenv, 0);
1348
+ param_count = (*jenv)->GetArrayLength(jenv, parama);
1349
+ rjb_check_exception(jenv, 0);
1350
+ setup_methodbase(jenv, &result->basic, parama, param_count);
1351
+ nm = (*jenv)->CallObjectMethod(jenv, m, method_getName);
1352
+ rjb_check_exception(jenv, 0);
1353
+ jname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1354
+ rname = ALLOCA_N(char, strlen(jname) * 2 + 8);
1355
+ make_alias(jname, rname);
1356
+ result->name = rb_intern(jname);
1357
+ rjb_release_string(jenv, nm, jname);
1358
+ result->basic.id = (*jenv)->FromReflectedMethod(jenv, m);
1359
+ rjb_check_exception(jenv, 0);
1360
+ cls = (*jenv)->CallObjectMethod(jenv, m, getReturnType);
1361
+ rjb_check_exception(jenv, 0);
1362
+ setup_j2r(jenv, cls, result, static_method);
1363
+ (*jenv)->DeleteLocalRef(jenv, cls);
1364
+ result->static_method = static_method;
1365
+ register_methodinfo(result, tbl);
1366
+ // create method alias
1367
+ pm = NULL;
1368
+ if (strlen(rname) > 3
1369
+ && (*rname == 'g' || *rname == 's') && *(rname + 1) == 'e' && *(rname + 2) == 't')
1370
+ {
1371
+ pm = clone_methodinfo(result);
1372
+ if (*rname == 's')
1373
+ {
1374
+ if (result->basic.arg_count == 1)
1375
+ {
1376
+ rname += 3;
1377
+ strcat(rname, "=");
1378
+ }
1379
+ }
1380
+ else
1381
+ {
1382
+ rname += 3;
1383
+ }
1384
+ if (*rname == '_') rname++;
1385
+ }
1386
+ else if (strlen(rname) > 2 && result->basic.result_signature == 'Z'
1387
+ && *rname == 'i' && *(rname + 1) == 's')
1388
+ {
1389
+ pm = clone_methodinfo(result);
1390
+ rname += 2;
1391
+ if (*rname == '_') rname++;
1392
+ strcat(rname, "?");
1393
+ }
1394
+ else
1395
+ {
1396
+ pm = clone_methodinfo(result);
1397
+ }
1398
+ if (pm)
1399
+ {
1400
+ pm->name = rb_intern(rname);
1401
+ register_methodinfo(pm, tbl);
1402
+ }
1403
+ }
1404
+
1405
+ static void create_fieldinfo(JNIEnv* jenv, st_table* tbl, jobject f, int readonly, int static_field)
1406
+ {
1407
+ struct cls_field* result;
1408
+ const char* jname;
1409
+ jstring nm;
1410
+ jobject cls;
1411
+ char sigs[256];
1412
+ off_t iv = 0;
1413
+ char sig = 0;
1414
+
1415
+ result = ALLOC(struct cls_field);
1416
+ memset(result, 0, sizeof(struct cls_field));
1417
+ nm = (*jenv)->CallObjectMethod(jenv, f, field_getName);
1418
+ rjb_check_exception(jenv, 0);
1419
+ jname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1420
+ result->name = rb_intern(jname);
1421
+ rjb_release_string(jenv, nm, jname);
1422
+ result->id = (*jenv)->FromReflectedField(jenv, f);
1423
+ rjb_check_exception(jenv, 0);
1424
+ cls = (*jenv)->CallObjectMethod(jenv, f, field_getType);
1425
+ rjb_check_exception(jenv, 0);
1426
+ result->value_convert = get_j2r(jenv, cls, &result->result_signature, &result->result_arraydepth, sigs, &iv, 0);
1427
+ result->arg_convert = get_r2j(jenv, cls, NULL, NULL);
1428
+ (*jenv)->DeleteLocalRef(jenv, cls);
1429
+ result->field_signature = ALLOC_N(char, strlen(sigs) + 1);
1430
+ strcpy(result->field_signature, sigs);
1431
+ if (!result->value_convert) result->value_convert = jv2rv;
1432
+ result->readonly = readonly;
1433
+ result->static_field = static_field;
1434
+ st_insert(tbl, result->name, (VALUE)result);
1435
+ }
1436
+
1437
+ static void setup_constructors(JNIEnv* jenv, struct cls_constructor*** pptr, jobjectArray methods)
1438
+ {
1439
+ int i;
1440
+ struct cls_constructor* pc;
1441
+ jsize mcount = (*jenv)->GetArrayLength(jenv, methods);
1442
+ struct cls_constructor** tbl = ALLOC_N(struct cls_constructor*, mcount + 1);
1443
+ *pptr = tbl;
1444
+ for (i = 0; i < mcount; i++)
1445
+ {
1446
+ jobjectArray parama;
1447
+ jsize pcount;
1448
+ jobject c = (*jenv)->GetObjectArrayElement(jenv, methods, i);
1449
+ rjb_check_exception(jenv, 0);
1450
+ pc = ALLOC(struct cls_constructor);
1451
+ tbl[i] = pc;
1452
+ parama = (*jenv)->CallObjectMethod(jenv, c, ctrGetParameterTypes);
1453
+ rjb_check_exception(jenv, 0);
1454
+ pcount = (*jenv)->GetArrayLength(jenv, parama);
1455
+ rjb_check_exception(jenv, 0);
1456
+ setup_methodbase(jenv, pc, parama, pcount);
1457
+ pc->id = (*jenv)->FromReflectedMethod(jenv, c);
1458
+ (*jenv)->DeleteLocalRef(jenv, c);
1459
+ }
1460
+ tbl[mcount] = NULL;
1461
+ }
1462
+
1463
+ static void setup_methods(JNIEnv* jenv, st_table** tbl, st_table** static_tbl,
1464
+ jobjectArray methods)
1465
+ {
1466
+ int i;
1467
+ jint modifier;
1468
+ jsize mcount = (*jenv)->GetArrayLength(jenv, methods);
1469
+ *tbl = st_init_numtable_with_size(mcount);
1470
+ *static_tbl = st_init_numtable();
1471
+ for (i = 0; i < mcount; i++)
1472
+ {
1473
+ jobject m = (*jenv)->GetObjectArrayElement(jenv, methods, i);
1474
+ rjb_check_exception(jenv, 0);
1475
+ modifier = (*jenv)->CallIntMethod(jenv, m, method_getModifiers);
1476
+ if (!(modifier & ACC_STATIC))
1477
+ {
1478
+ create_methodinfo(jenv, *tbl, m, 0);
1479
+ }
1480
+ else
1481
+ {
1482
+ create_methodinfo(jenv, *static_tbl, m, 1);
1483
+ }
1484
+ (*jenv)->DeleteLocalRef(jenv, m);
1485
+ }
1486
+ }
1487
+
1488
+ static void setup_fields(JNIEnv* jenv, st_table** tbl, jobjectArray flds)
1489
+ {
1490
+ int i;
1491
+ jint modifier;
1492
+ jsize fcount = (*jenv)->GetArrayLength(jenv, flds);
1493
+ *tbl = st_init_numtable_with_size(fcount);
1494
+ for (i = 0; i < fcount; i++)
1495
+ {
1496
+ jobject f = (*jenv)->GetObjectArrayElement(jenv, flds, i);
1497
+ rjb_check_exception(jenv, 0);
1498
+ modifier = (*jenv)->CallIntMethod(jenv, f, field_getModifiers);
1499
+ create_fieldinfo(jenv, *tbl, f, modifier & ACC_FINAL, modifier & ACC_STATIC);
1500
+ (*jenv)->DeleteLocalRef(jenv, f);
1501
+ }
1502
+ }
1503
+
1504
+ static void load_constants(JNIEnv* jenv, jclass klass, VALUE self, jobjectArray flds)
1505
+ {
1506
+ int i;
1507
+ jint modifier;
1508
+ jsize fcount = (*jenv)->GetArrayLength(jenv, flds);
1509
+ for (i = 0; i < fcount; i++)
1510
+ {
1511
+ jobject f = (*jenv)->GetObjectArrayElement(jenv, flds, i);
1512
+ rjb_check_exception(jenv, 0);
1513
+ modifier = (*jenv)->CallIntMethod(jenv, f, field_getModifiers);
1514
+ rjb_check_exception(jenv, 0);
1515
+ if ((modifier & (ACC_PUBLIC | ACC_STATIC | ACC_FINAL)) == (ACC_PUBLIC | ACC_STATIC | ACC_FINAL))
1516
+ {
1517
+ jstring nm;
1518
+ const char* cname;
1519
+ jobject cls;
1520
+ char sig;
1521
+ char depth;
1522
+ off_t iv;
1523
+ J2R j2r;
1524
+ jvalue jv;
1525
+ jfieldID jfid;
1526
+ char sigs[256];
1527
+ char* pname;
1528
+
1529
+ // constants make define directly in the ruby object
1530
+ cls = (*jenv)->CallObjectMethod(jenv, f, field_getType);
1531
+ rjb_check_exception(jenv, 0);
1532
+ iv = 0;
1533
+ sig = depth = 0;
1534
+ j2r = get_j2r(jenv, cls, &sig, &depth, sigs, &iv, 1);
1535
+ if (!j2r) j2r = jv2rv;
1536
+ (*jenv)->DeleteLocalRef(jenv, cls);
1537
+ nm = (*jenv)->CallObjectMethod(jenv, f, field_getName);
1538
+ rjb_check_exception(jenv, 0);
1539
+ cname = (*jenv)->GetStringUTFChars(jenv, nm, NULL);
1540
+ rjb_check_exception(jenv, 0);
1541
+ jfid = (*jenv)->GetStaticFieldID(jenv, klass, cname, sigs);
1542
+ rjb_check_exception(jenv, 0);
1543
+ switch (sig)
1544
+ {
1545
+ case 'D':
1546
+ jv.d = (*jenv)->GetStaticDoubleField(jenv, klass, jfid);
1547
+ break;
1548
+ case 'Z':
1549
+ jv.z = (*jenv)->GetStaticBooleanField(jenv, klass, jfid);
1550
+ break;
1551
+ case 'B':
1552
+ jv.b = (*jenv)->GetStaticByteField(jenv, klass, jfid);
1553
+ break;
1554
+ case 'F':
1555
+ jv.f = (*jenv)->GetStaticFloatField(jenv, klass, jfid);
1556
+ break;
1557
+ case 'C':
1558
+ jv.c = (*jenv)->GetStaticCharField(jenv, klass, jfid);
1559
+ break;
1560
+ case 'S':
1561
+ jv.s = (*jenv)->GetStaticShortField(jenv, klass, jfid);
1562
+ break;
1563
+ case 'J':
1564
+ jv.j = (*jenv)->GetStaticLongField(jenv, klass, jfid);
1565
+ break;
1566
+ case 'I':
1567
+ jv.i = (*jenv)->GetStaticIntField(jenv, klass, jfid);
1568
+ break;
1569
+ default:
1570
+ jv.l = (*jenv)->GetStaticObjectField(jenv, klass, jfid);
1571
+ break;
1572
+ }
1573
+ pname = (char*)cname;
1574
+ if (!isupper(*cname))
1575
+ {
1576
+ pname = ALLOCA_N(char, strlen(cname) + 1);
1577
+ strcpy(pname, cname);
1578
+ *pname = toupper(*pname);
1579
+ if (!isupper(*pname)
1580
+ || rb_const_defined(RBASIC(self)->klass, rb_intern(pname)))
1581
+ {
1582
+ pname = NULL;
1583
+ }
1584
+ }
1585
+ if (pname)
1586
+ {
1587
+ rb_define_const(RBASIC(self)->klass, pname, j2r(jenv, jv));
1588
+ }
1589
+ rjb_release_string(jenv, nm, cname);
1590
+ }
1591
+ (*jenv)->DeleteLocalRef(jenv, f);
1592
+ }
1593
+ }
1594
+
1595
+ static void setup_metadata(JNIEnv* jenv, VALUE self, struct jv_data* ptr, VALUE classname)
1596
+ {
1597
+ jmethodID mid;
1598
+ jobjectArray methods;
1599
+ jobjectArray flds;
1600
+
1601
+ jclass klass = (*jenv)->GetObjectClass(jenv, ptr->idata.obj);
1602
+ ptr->idata.klass = (*jenv)->NewGlobalRef(jenv, klass);
1603
+ rjb_check_exception(jenv, 0);
1604
+ mid = (*jenv)->GetMethodID(jenv, klass, "getMethods", "()[Ljava/lang/reflect/Method;");
1605
+ rjb_check_exception(jenv, 0);
1606
+ methods = (*jenv)->CallNonvirtualObjectMethod(jenv, ptr->idata.obj, klass, mid);
1607
+ rjb_check_exception(jenv, 0);
1608
+ setup_methods(jenv, &ptr->idata.methods, &ptr->static_methods, methods);
1609
+ mid = (*jenv)->GetMethodID(jenv, klass, "getConstructors", "()[Ljava/lang/reflect/Constructor;");
1610
+ rjb_check_exception(jenv, 0);
1611
+ methods = (*jenv)->CallNonvirtualObjectMethod(jenv, ptr->idata.obj, klass, mid);
1612
+ rjb_check_exception(jenv, 0);
1613
+ setup_constructors(jenv, &ptr->constructors, methods);
1614
+ mid = (*jenv)->GetMethodID(jenv, klass, "getFields", "()[Ljava/lang/reflect/Field;");
1615
+ rjb_check_exception(jenv, 0);
1616
+ flds = (*jenv)->CallNonvirtualObjectMethod(jenv, ptr->idata.obj, klass, mid);
1617
+ rjb_check_exception(jenv, 0);
1618
+ setup_fields(jenv, &ptr->idata.fields, flds);
1619
+
1620
+ register_class(self, classname);
1621
+ load_constants(jenv, ptr->idata.obj, self, flds);
1622
+ }
1623
+
1624
+ /*
1625
+ * load Java Virtual Machine
1626
+ * def load(class_path = '', vmargs = [])
1627
+ * class_path: passes for the class dir and jar name
1628
+ * vmargs: strng array of vmarg (such as -Xrs)
1629
+ *
1630
+ * change in rjb 0.1.7, omit first argument for JNI version.
1631
+ * because I misunderstood the number means (JVM but JNI).
1632
+ */
1633
+ static VALUE rjb_s_load(int argc, VALUE* argv, VALUE self)
1634
+ {
1635
+ JNIEnv* jenv;
1636
+ JavaVMInitArgs vm_args;
1637
+ jint res;
1638
+ VALUE user_path;
1639
+ VALUE vm_argv;
1640
+ char* userpath;
1641
+ int i;
1642
+ jclass jmethod;
1643
+ jclass jfield;
1644
+ jclass jconstructor;
1645
+
1646
+ if (rjb_jvm)
1647
+ {
1648
+ return Qnil;
1649
+ }
1650
+
1651
+ memset(&vm_args, 0, sizeof(vm_args));
1652
+ vm_args.version = JNI_VERSION_1_4;
1653
+ rb_scan_args(argc, argv, "02", &user_path, &vm_argv);
1654
+ if (!NIL_P(user_path))
1655
+ {
1656
+ Check_Type(user_path, T_STRING);
1657
+ userpath = StringValueCStr(user_path);
1658
+ }
1659
+ else
1660
+ {
1661
+ userpath = ".";
1662
+ }
1663
+ if (!NIL_P(vm_argv))
1664
+ {
1665
+ Check_Type(vm_argv, T_ARRAY);
1666
+ }
1667
+ jenv = NULL;
1668
+ res = rjb_create_jvm(&jenv, &vm_args, userpath, vm_argv);
1669
+ if (res < 0)
1670
+ {
1671
+ rjb_jvm = NULL;
1672
+ rb_raise(rb_eRuntimeError, "can't create Java VM");
1673
+ } else {
1674
+ main_jenv = jenv;
1675
+ }
1676
+
1677
+ jconstructor = (*jenv)->FindClass(jenv, "java/lang/reflect/Constructor");
1678
+ rjb_check_exception(jenv, 1);
1679
+ ctrGetParameterTypes = (*jenv)->GetMethodID(jenv, jconstructor, "getParameterTypes", "()[Ljava/lang/Class;");
1680
+ rjb_check_exception(jenv, 1);
1681
+ jmethod = (*jenv)->FindClass(jenv, "java/lang/reflect/Method");
1682
+ method_getModifiers = (*jenv)->GetMethodID(jenv, jmethod, "getModifiers", "()I");
1683
+ rjb_check_exception(jenv, 1);
1684
+ method_getName = (*jenv)->GetMethodID(jenv, jmethod, "getName", "()Ljava/lang/String;");
1685
+ rjb_check_exception(jenv, 1);
1686
+ getParameterTypes = (*jenv)->GetMethodID(jenv, jmethod, "getParameterTypes", "()[Ljava/lang/Class;");
1687
+ rjb_check_exception(jenv, 1);
1688
+ getReturnType = (*jenv)->GetMethodID(jenv, jmethod, "getReturnType", "()Ljava/lang/Class;");
1689
+ rjb_check_exception(jenv, 1);
1690
+
1691
+ jfield = (*jenv)->FindClass(jenv, "java/lang/reflect/Field");
1692
+ field_getModifiers = (*jenv)->GetMethodID(jenv, jfield, "getModifiers", "()I");
1693
+ rjb_check_exception(jenv, 1);
1694
+ field_getName = (*jenv)->GetMethodID(jenv, jfield, "getName", "()Ljava/lang/String;");
1695
+ rjb_check_exception(jenv, 1);
1696
+ field_getType = (*jenv)->GetMethodID(jenv, jfield, "getType", "()Ljava/lang/Class;");
1697
+ rjb_check_exception(jenv, 1);
1698
+
1699
+ j_class = (*jenv)->FindClass(jenv, "java/lang/Class");
1700
+ rjb_check_exception(jenv, 1);
1701
+ rjb_class_getName = (*jenv)->GetMethodID(jenv, j_class, "getName", "()Ljava/lang/String;");
1702
+ rjb_check_exception(jenv, 1);
1703
+ j_class = (*jenv)->NewGlobalRef(jenv, j_class);
1704
+
1705
+ rjb_j_throwable = (*jenv)->FindClass(jenv, "java/lang/Throwable");
1706
+ rjb_check_exception(jenv, 1);
1707
+ rjb_throwable_getMessage = (*jenv)->GetMethodID(jenv, rjb_j_throwable, "getMessage", "()Ljava/lang/String;");
1708
+ rjb_check_exception(jenv, 1);
1709
+
1710
+ j_string = (*jenv)->FindClass(jenv, "java/lang/String");
1711
+ rjb_check_exception(jenv, 1);
1712
+ str_tostring = (*jenv)->GetMethodID(jenv, j_string, "toString", "()Ljava/lang/String;");
1713
+ rjb_check_exception(jenv, 1);
1714
+ j_string = (*jenv)->NewGlobalRef(jenv, j_string);
1715
+
1716
+ j_object = (*jenv)->FindClass(jenv, "java/lang/Object");
1717
+ rjb_check_exception(jenv, 1);
1718
+ j_object = (*jenv)->NewGlobalRef(jenv, j_object);
1719
+
1720
+ for (i = PRM_INT; i < PRM_LAST; i++)
1721
+ {
1722
+ jclass klass = (*jenv)->FindClass(jenv, jpcvt[i].classname);
1723
+ if (i == PRM_BOOLEAN)
1724
+ {
1725
+ jpcvt[i].ctr_id = (*jenv)->GetStaticMethodID(jenv,
1726
+ klass, "valueOf", jpcvt[i].ctrsig);
1727
+ rjb_check_exception(jenv, 1);
1728
+ }
1729
+ else if (jpcvt[i].ctrsig)
1730
+ {
1731
+ jpcvt[i].ctr_id = (*jenv)->GetMethodID(jenv, klass,
1732
+ "<init>", jpcvt[i].ctrsig);
1733
+ rjb_check_exception(jenv, 1);
1734
+ }
1735
+ jpcvt[i].to_prim_id = (*jenv)->GetMethodID(jenv, klass,
1736
+ jpcvt[i].to_prim_method, jpcvt[i].prmsig);
1737
+ rjb_check_exception(jenv, 1);
1738
+ jpcvt[i].klass = (*jenv)->NewGlobalRef(jenv, klass);
1739
+ }
1740
+
1741
+ jklass = import_class(jenv, j_class, rb_str_new2("java.lang.Class"));
1742
+ rb_define_method(RBASIC(jklass)->klass, "forName", rjb_class_forname, -1);
1743
+ rb_gc_register_address(&jklass);
1744
+
1745
+ return Qnil;
1746
+ }
1747
+
1748
+ /*
1749
+ * unload Java Virtual Machine
1750
+ *
1751
+ * def unload()
1752
+ * classes.clear
1753
+ * unload(jvm)
1754
+ * end
1755
+ */
1756
+ static int clear_classes(VALUE key, VALUE val, VALUE dummy)
1757
+ {
1758
+ return ST_DELETE;
1759
+ }
1760
+ static VALUE rjb_s_unload(int argc, VALUE* argv, VALUE self)
1761
+ {
1762
+ st_foreach(RHASH_TBL(rjb_loaded_classes), clear_classes, 0);
1763
+ if (rjb_jvm)
1764
+ {
1765
+ (*rjb_jvm)->DestroyJavaVM(rjb_jvm);
1766
+ rjb_jvm = NULL;
1767
+ }
1768
+ return Qnil;
1769
+ }
1770
+
1771
+ /*
1772
+ * return all classes that were already loaded.
1773
+ * this method simply returns the global hash,
1774
+ * but it's safe because the hash was frozen.
1775
+ */
1776
+ static VALUE rjb_s_classes(VALUE self)
1777
+ {
1778
+ return rjb_loaded_classes;
1779
+ }
1780
+
1781
+ /**
1782
+ * For JRuby conpatible optsion
1783
+ */
1784
+ static VALUE rjb_s_set_pconversion(VALUE self, VALUE val)
1785
+ {
1786
+ primitive_conversion = (RTEST(val)) ? Qtrue : Qfalse;
1787
+ return val;
1788
+ }
1789
+
1790
+ /**
1791
+ * For JRuby conpatible optsion
1792
+ */
1793
+ static VALUE rjb_s_get_pconversion(VALUE self)
1794
+ {
1795
+ return primitive_conversion;
1796
+ }
1797
+
1798
+
1799
+ /*
1800
+ * free java class
1801
+ */
1802
+ static void free_constructor(struct cls_constructor* p)
1803
+ {
1804
+ free(p->arg_convert);
1805
+ free(p->method_signature);
1806
+ }
1807
+ static int free_method_item(ID key, struct cls_method* pm, int dummy)
1808
+ {
1809
+ for (; pm; pm = pm->next)
1810
+ {
1811
+ free_constructor(&pm->basic);
1812
+ }
1813
+ return ST_CONTINUE;
1814
+ }
1815
+
1816
+ /*
1817
+ * finalize Object instance
1818
+ */
1819
+ static VALUE rjb_delete_ref(struct jvi_data* ptr)
1820
+ {
1821
+ JNIEnv* jenv = rjb_attach_current_thread();
1822
+ if (jenv)
1823
+ {
1824
+ (*jenv)->DeleteGlobalRef(jenv, ptr->obj);
1825
+ }
1826
+ return Qnil;
1827
+ }
1828
+
1829
+ /*
1830
+ * finalize Bridge instance
1831
+ */
1832
+ static VALUE rj_bridge_free(struct rj_bridge* ptr)
1833
+ {
1834
+ JNIEnv* jenv = rjb_attach_current_thread();
1835
+ (*jenv)->DeleteLocalRef(jenv, ptr->proxy);
1836
+ (*jenv)->DeleteLocalRef(jenv, ptr->bridge);
1837
+ return Qnil;
1838
+ }
1839
+
1840
+ /*
1841
+ * mark wrapped object in the Bridge
1842
+ */
1843
+ static void rj_bridge_mark(struct rj_bridge* ptr)
1844
+ {
1845
+ rb_gc_mark(ptr->wrapped);
1846
+ }
1847
+
1848
+ /*
1849
+ * finalize Class instance
1850
+ */
1851
+ static VALUE rjb_s_free(struct jv_data* ptr)
1852
+ {
1853
+ /* class never delete
1854
+ JNIEnv* jenv = rjb_attach_current_thread();
1855
+ struct cls_constructor** c;
1856
+
1857
+ rjb_delete_ref(&ptr->idata);
1858
+ if (ptr->constructors)
1859
+ {
1860
+ for (c = ptr->constructors; *c; c++)
1861
+ {
1862
+ free_constructor(*c);
1863
+ }
1864
+ }
1865
+ free(ptr->constructors);
1866
+ if (ptr->idata.methods)
1867
+ {
1868
+ st_foreach(ptr->idata.methods, (int(*)())free_method_item, 0);
1869
+ st_free_table(ptr->idata.methods);
1870
+ }
1871
+ (*jenv)->DeleteGlobalRef(jenv, ptr->idata.klass);
1872
+ st_delete(RHASH(rjb_loaded_classes)->tbl, clsname, NULL);
1873
+ */
1874
+ return Qnil;
1875
+ }
1876
+
1877
+ /*
1878
+ * create new instance of this class
1879
+ */
1880
+ static VALUE createinstance(JNIEnv* jenv, int argc, VALUE* argv,
1881
+ struct jvi_data* org, struct cls_constructor* pc)
1882
+ {
1883
+ int i;
1884
+ char* psig = pc->method_signature;
1885
+ jobject obj = NULL;
1886
+ VALUE result;
1887
+
1888
+ jvalue* args = (argc) ? ALLOCA_N(jvalue, argc) : NULL;
1889
+ for (i = 0; i < argc; i++)
1890
+ {
1891
+ R2J pr2j = *(pc->arg_convert + i);
1892
+ pr2j(jenv, argv[i], args + i, psig, 0);
1893
+ psig = next_sig(psig);
1894
+ rjb_check_exception(jenv, 1);
1895
+ }
1896
+ obj = (*jenv)->NewObjectA(jenv, org->obj, pc->id, args);
1897
+ if (!obj)
1898
+ {
1899
+ rjb_check_exception(jenv, 1);
1900
+ }
1901
+ psig = pc->method_signature;
1902
+ for (i = 0; i < argc; i++)
1903
+ {
1904
+ R2J pr2j = *(pc->arg_convert + i);
1905
+ pr2j(jenv, argv[i], args + i, psig, 1);
1906
+ psig = next_sig(psig);
1907
+ }
1908
+
1909
+ result = register_instance(jenv, org, obj);
1910
+ (*jenv)->DeleteLocalRef(jenv, obj);
1911
+ return result;
1912
+ }
1913
+
1914
+ static VALUE import_class(JNIEnv* jenv, jclass jcls, VALUE clsname)
1915
+ {
1916
+ VALUE v;
1917
+ VALUE rexp;
1918
+ struct jv_data* ptr;
1919
+ char* pclsname = StringValueCStr(clsname);
1920
+ char* nm = ALLOCA_N(char, strlen(pclsname) + 1);
1921
+ strcpy(nm, pclsname);
1922
+ *nm = toupper(*nm);
1923
+ for (pclsname = nm; *pclsname; pclsname++)
1924
+ {
1925
+ if (*pclsname == '.')
1926
+ {
1927
+ *pclsname = '_';
1928
+ }
1929
+ }
1930
+ rexp = rb_define_class_under(rjb, nm, rjbc);
1931
+ ptr = ALLOC(struct jv_data);
1932
+ memset(ptr, 0, sizeof(struct jv_data));
1933
+ v = Data_Wrap_Struct(rexp, NULL, rjb_s_free, ptr);
1934
+ ptr->idata.obj = (*jenv)->NewGlobalRef(jenv, jcls);
1935
+ setup_metadata(jenv, v, ptr, clsname);
1936
+ return v;
1937
+ }
1938
+
1939
+ static VALUE register_instance(JNIEnv* jenv, struct jvi_data* org, jobject obj)
1940
+ {
1941
+ VALUE v;
1942
+ struct jvi_data* ptr = ALLOC(struct jvi_data);
1943
+ memset(ptr, 0, sizeof(struct jvi_data));
1944
+ v = Data_Wrap_Struct(rjbi, NULL, rjb_delete_ref, ptr);
1945
+ ptr->klass = org->obj;
1946
+ ptr->obj = (*jenv)->NewGlobalRef(jenv, obj);
1947
+ ptr->methods = org->methods;
1948
+ ptr->fields = org->fields;
1949
+ return v;
1950
+ }
1951
+
1952
+ /*
1953
+ * temporary signature check
1954
+ * return !0 if found
1955
+ */
1956
+ static int check_rtype(JNIEnv* jenv, VALUE v, char* p)
1957
+ {
1958
+ char* pcls = NULL;
1959
+ if (*p == 'L')
1960
+ {
1961
+ char* pt = strchr(p, ';');
1962
+ if (pt)
1963
+ {
1964
+ int len = pt - p - 1;
1965
+ pcls = ALLOCA_N(char, len + 1);
1966
+ strncpy(pcls, p + 1, len);
1967
+ *(pcls + len) = '\0';
1968
+ }
1969
+ }
1970
+ if (pcls && !strcmp("java.lang.Object", pcls))
1971
+ {
1972
+ return 1;
1973
+ }
1974
+ switch (TYPE(v))
1975
+ {
1976
+ case T_FIXNUM:
1977
+ return strchr("BCDFIJS", *p) != NULL;
1978
+ case T_FLOAT:
1979
+ return strchr("DF", *p) != NULL;
1980
+ case T_STRING:
1981
+ return pcls && !strcmp("java.lang.String", pcls);
1982
+ case T_TRUE:
1983
+ case T_FALSE:
1984
+ return *p == 'Z';
1985
+ case T_ARRAY:
1986
+ return *p == '[';
1987
+ case T_DATA:
1988
+ if (RBASIC(v)->klass == rjbi && pcls)
1989
+ {
1990
+ // imported object
1991
+ jclass cls;
1992
+ struct jvi_data* ptr;
1993
+ int result = 0;
1994
+ if (!strcmp("java.lang.String", pcls)) return 1;
1995
+ Data_Get_Struct(v, struct jvi_data, ptr);
1996
+ cls = (*jenv)->FindClass(jenv, java2jniname(pcls));
1997
+ if (cls)
1998
+ {
1999
+ result = (cls && (*jenv)->IsInstanceOf(jenv, ptr->obj, cls));
2000
+ (*jenv)->DeleteLocalRef(jenv, cls);
2001
+ }
2002
+ return result;
2003
+ }
2004
+ // fall down to the next case
2005
+ case T_OBJECT:
2006
+ // fall down to the next case
2007
+ default:
2008
+ if (pcls || *p == '[')
2009
+ {
2010
+ return 1;
2011
+ }
2012
+ return 0;
2013
+ }
2014
+ }
2015
+
2016
+ /*
2017
+ * new instance with signature
2018
+ */
2019
+ static VALUE rjb_newinstance_s(int argc, VALUE* argv, VALUE self)
2020
+ {
2021
+ VALUE vsig, rest;
2022
+ char* sig;
2023
+ VALUE ret = Qnil;
2024
+ struct jv_data* ptr;
2025
+ JNIEnv* jenv = rjb_attach_current_thread();
2026
+ int found = 0;
2027
+
2028
+ rb_scan_args(argc, argv, "1*", &vsig, &rest);
2029
+ sig = StringValueCStr(vsig);
2030
+ Data_Get_Struct(self, struct jv_data, ptr);
2031
+ if (ptr->constructors)
2032
+ {
2033
+ struct cls_constructor** pc = ptr->constructors;
2034
+ for (pc = ptr->constructors; *pc; pc++)
2035
+ {
2036
+ if ((*pc)->arg_count == argc - 1
2037
+ && !strcmp(sig, (*pc)->method_signature))
2038
+ {
2039
+ found = 1;
2040
+ ret = createinstance(jenv, argc - 1, argv + 1, &ptr->idata, *pc);
2041
+ break;
2042
+ }
2043
+ }
2044
+ }
2045
+ if (!found) {
2046
+ rb_raise(rb_eRuntimeError, "Constructor not found");
2047
+ }
2048
+ return ret;
2049
+ }
2050
+
2051
+ static VALUE rjb_newinstance(int argc, VALUE* argv, VALUE self)
2052
+ {
2053
+ VALUE ret = Qnil;
2054
+ struct jv_data* ptr;
2055
+ struct cls_constructor** pc;
2056
+ JNIEnv* jenv = rjb_attach_current_thread();
2057
+ int found = 0;
2058
+
2059
+ Data_Get_Struct(self, struct jv_data, ptr);
2060
+
2061
+ if (ptr->constructors)
2062
+ {
2063
+ int i;
2064
+ char* psig;
2065
+ for (pc = ptr->constructors; *pc; pc++)
2066
+ {
2067
+ if ((*pc)->arg_count == argc)
2068
+ {
2069
+ found = 1;
2070
+ psig = (*pc)->method_signature;
2071
+ for (i = 0; i < argc; i++)
2072
+ {
2073
+ if (!check_rtype(jenv, *(argv + i), psig))
2074
+ {
2075
+ found = 0;
2076
+ break;
2077
+ }
2078
+ psig = next_sig(psig);
2079
+ }
2080
+ if (found)
2081
+ {
2082
+ ret = createinstance(jenv, argc, argv, &ptr->idata, *pc);
2083
+ break;
2084
+ }
2085
+ }
2086
+ }
2087
+ }
2088
+ if (!found) {
2089
+ rb_raise(rb_eRuntimeError, "Constructor not found");
2090
+ }
2091
+ return ret;
2092
+ }
2093
+
2094
+ /*
2095
+ * find java class from classname
2096
+ */
2097
+ jclass rjb_find_class(JNIEnv* jenv, VALUE name)
2098
+ {
2099
+ char* cname;
2100
+ char* jnicls;
2101
+
2102
+ cname = StringValueCStr(name);
2103
+ jnicls = ALLOCA_N(char, strlen(cname) + 1);
2104
+ strcpy(jnicls, cname);
2105
+ return (*jenv)->FindClass(jenv, java2jniname(jnicls));
2106
+ }
2107
+
2108
+ /*
2109
+ * jclass Rjb::bind(rbobj, interface_name)
2110
+ */
2111
+ static VALUE rjb_s_bind(VALUE self, VALUE rbobj, VALUE itfname)
2112
+ {
2113
+ VALUE result = Qnil;
2114
+ JNIEnv* jenv = rjb_attach_current_thread();
2115
+
2116
+ jclass itf = rjb_find_class(jenv, itfname);
2117
+ rjb_check_exception(jenv, 1);
2118
+ if (itf)
2119
+ {
2120
+ struct rj_bridge* ptr = ALLOC(struct rj_bridge);
2121
+ memset(ptr, 0, sizeof(struct rj_bridge));
2122
+ ptr->bridge = (*jenv)->NewGlobalRef(jenv,
2123
+ (*jenv)->AllocObject(jenv, rjb_rbridge));
2124
+ if (!ptr->bridge)
2125
+ {
2126
+ free(ptr);
2127
+ rjb_check_exception(jenv, 1);
2128
+ return Qnil;
2129
+ }
2130
+ ptr->proxy = (*jenv)->CallObjectMethod(jenv, ptr->bridge,
2131
+ rjb_register_bridge, itf);
2132
+ ptr->proxy = (*jenv)->NewGlobalRef(jenv, ptr->proxy);
2133
+ ptr->wrapped = rbobj;
2134
+ result = Data_Wrap_Struct(rjbb, rj_bridge_mark, rj_bridge_free, ptr);
2135
+ rb_ary_push(proxies, result);
2136
+ }
2137
+ return result;
2138
+ }
2139
+
2140
+ /*
2141
+ * Jclass Rjb::import(classname)
2142
+ */
2143
+ static VALUE rjb_s_import(VALUE self, VALUE clsname)
2144
+ {
2145
+ JNIEnv* jenv;
2146
+ jclass jcls;
2147
+ VALUE v = rb_hash_aref(rjb_loaded_classes, clsname);
2148
+ if (v != Qnil)
2149
+ {
2150
+ return v;
2151
+ }
2152
+
2153
+ if (!rjb_jvm)
2154
+ {
2155
+ /* auto-load with default setting */
2156
+ rjb_s_load(0, NULL, 0);
2157
+ }
2158
+ jenv = rjb_attach_current_thread();
2159
+ jcls = rjb_find_class(jenv, clsname);
2160
+ if (!jcls)
2161
+ {
2162
+ rjb_check_exception(jenv, 0);
2163
+ rb_raise(rb_eRuntimeError, "`%s' not found", StringValueCStr(clsname));
2164
+ }
2165
+ v = import_class(jenv, jcls, clsname);
2166
+ return v;
2167
+ }
2168
+
2169
+ static void register_class(VALUE self, VALUE clsname)
2170
+ {
2171
+ rb_define_singleton_method(self, "new", rjb_newinstance, -1);
2172
+ rb_define_singleton_method(self, "new_with_sig", rjb_newinstance_s, -1);
2173
+ /*
2174
+ * the hash was frozen, so it need to call st_ func directly.
2175
+ */
2176
+ st_insert(RHASH_TBL(rjb_loaded_classes), clsname, self);
2177
+ }
2178
+
2179
+ /*
2180
+ * return class name
2181
+ */
2182
+ static VALUE rjb_i_class(VALUE self)
2183
+ {
2184
+ JNIEnv* jenv = rjb_attach_current_thread();
2185
+ struct jvi_data* ptr;
2186
+ jstring nm;
2187
+ Data_Get_Struct(self, struct jvi_data, ptr);
2188
+ nm = (*jenv)->CallObjectMethod(jenv, ptr->klass, rjb_class_getName);
2189
+ rjb_check_exception(jenv, 0);
2190
+ return jstring2val(jenv, nm);
2191
+ }
2192
+
2193
+ /*
2194
+ * invoker
2195
+ */
2196
+ static VALUE getter(JNIEnv* jenv, struct cls_field* pf, struct jvi_data* ptr)
2197
+ {
2198
+ jvalue jv;
2199
+ switch (pf->result_signature)
2200
+ {
2201
+ case 'D':
2202
+ if (pf->static_field)
2203
+ {
2204
+ jv.d = (*jenv)->GetStaticDoubleField(jenv, ptr->klass, pf->id);
2205
+ }
2206
+ else
2207
+ {
2208
+ jv.d = (*jenv)->GetDoubleField(jenv, ptr->obj, pf->id);
2209
+ }
2210
+ break;
2211
+ case 'Z':
2212
+ if (pf->static_field)
2213
+ {
2214
+ jv.z = (*jenv)->GetStaticBooleanField(jenv, ptr->klass, pf->id);
2215
+ }
2216
+ else
2217
+ {
2218
+ jv.z = (*jenv)->GetBooleanField(jenv, ptr->obj, pf->id);
2219
+ }
2220
+ break;
2221
+ case 'B':
2222
+ if (pf->static_field)
2223
+ {
2224
+ jv.b = (*jenv)->GetStaticByteField(jenv, ptr->klass, pf->id);
2225
+ }
2226
+ else
2227
+ {
2228
+ jv.b = (*jenv)->GetByteField(jenv, ptr->obj, pf->id);
2229
+ }
2230
+ break;
2231
+ case 'F':
2232
+ if (pf->static_field)
2233
+ {
2234
+ jv.f = (*jenv)->GetStaticFloatField(jenv, ptr->klass, pf->id);
2235
+ }
2236
+ else
2237
+ {
2238
+ jv.f = (*jenv)->GetFloatField(jenv, ptr->obj, pf->id);
2239
+ }
2240
+ break;
2241
+ case 'C':
2242
+ if (pf->static_field)
2243
+ {
2244
+ jv.c = (*jenv)->GetStaticCharField(jenv, ptr->klass, pf->id);
2245
+ }
2246
+ else
2247
+ {
2248
+ jv.c = (*jenv)->GetCharField(jenv, ptr->obj, pf->id);
2249
+ }
2250
+ break;
2251
+ case 'S':
2252
+ if (pf->static_field)
2253
+ {
2254
+ jv.s = (*jenv)->GetStaticShortField(jenv, ptr->klass, pf->id);
2255
+ }
2256
+ else
2257
+ {
2258
+ jv.s = (*jenv)->GetShortField(jenv, ptr->obj, pf->id);
2259
+ }
2260
+ break;
2261
+ case 'J':
2262
+ if (pf->static_field)
2263
+ {
2264
+ jv.j = (*jenv)->GetStaticLongField(jenv, ptr->klass, pf->id);
2265
+ }
2266
+ else
2267
+ {
2268
+ jv.j = (*jenv)->GetLongField(jenv, ptr->obj, pf->id);
2269
+ }
2270
+ break;
2271
+ case 'I':
2272
+ if (pf->static_field)
2273
+ {
2274
+ jv.i = (*jenv)->GetStaticIntField(jenv, ptr->klass, pf->id);
2275
+ }
2276
+ else
2277
+ {
2278
+ jv.i = (*jenv)->GetIntField(jenv, ptr->obj, pf->id);
2279
+ }
2280
+ break;
2281
+ default:
2282
+ if (pf->static_field)
2283
+ {
2284
+ jv.l = (*jenv)->GetStaticObjectField(jenv, ptr->klass, pf->id);
2285
+ }
2286
+ else
2287
+ {
2288
+ jv.l = (*jenv)->GetObjectField(jenv, ptr->obj, pf->id);
2289
+ }
2290
+ break;
2291
+ }
2292
+ if (pf->result_arraydepth)
2293
+ {
2294
+ return ja2r(pf->value_convert, jenv, jv, pf->result_arraydepth);
2295
+ }
2296
+ else
2297
+ {
2298
+ return pf->value_convert(jenv, jv);
2299
+ }
2300
+ }
2301
+
2302
+ static void setter(JNIEnv* jenv, struct cls_field* pf, struct jvi_data* ptr, VALUE val)
2303
+ {
2304
+ jvalue jv;
2305
+ pf->arg_convert(jenv, val, &jv, pf->field_signature, 0);
2306
+ switch (*pf->field_signature)
2307
+ {
2308
+ case 'D':
2309
+ if (pf->static_field)
2310
+ {
2311
+ (*jenv)->SetStaticDoubleField(jenv, ptr->klass, pf->id, jv.d);
2312
+ }
2313
+ else
2314
+ {
2315
+ (*jenv)->SetDoubleField(jenv, ptr->obj, pf->id, jv.d);
2316
+ }
2317
+ break;
2318
+ case 'Z':
2319
+ if (pf->static_field)
2320
+ {
2321
+ (*jenv)->SetStaticBooleanField(jenv, ptr->klass, pf->id, jv.z);
2322
+ }
2323
+ else
2324
+ {
2325
+ (*jenv)->SetBooleanField(jenv, ptr->obj, pf->id, jv.z);
2326
+ }
2327
+ break;
2328
+ case 'B':
2329
+ if (pf->static_field)
2330
+ {
2331
+ (*jenv)->SetStaticByteField(jenv, ptr->klass, pf->id, jv.b);
2332
+ }
2333
+ else
2334
+ {
2335
+ (*jenv)->SetByteField(jenv, ptr->obj, pf->id, jv.b);
2336
+ }
2337
+ break;
2338
+ case 'F':
2339
+ if (pf->static_field)
2340
+ {
2341
+ (*jenv)->SetStaticFloatField(jenv, ptr->klass, pf->id, jv.f);
2342
+ }
2343
+ else
2344
+ {
2345
+ (*jenv)->SetFloatField(jenv, ptr->obj, pf->id, jv.f);
2346
+ }
2347
+ break;
2348
+ case 'C':
2349
+ if (pf->static_field)
2350
+ {
2351
+ (*jenv)->SetStaticCharField(jenv, ptr->klass, pf->id, jv.c);
2352
+ }
2353
+ else
2354
+ {
2355
+ (*jenv)->SetCharField(jenv, ptr->obj, pf->id, jv.c);
2356
+ }
2357
+ break;
2358
+ case 'S':
2359
+ if (pf->static_field)
2360
+ {
2361
+ (*jenv)->SetStaticShortField(jenv, ptr->klass, pf->id, jv.s);
2362
+ }
2363
+ else
2364
+ {
2365
+ (*jenv)->SetShortField(jenv, ptr->obj, pf->id, jv.s);
2366
+ }
2367
+ break;
2368
+ case 'J':
2369
+ if (pf->static_field)
2370
+ {
2371
+ (*jenv)->SetStaticLongField(jenv, ptr->klass, pf->id, jv.j);
2372
+ }
2373
+ else
2374
+ {
2375
+ (*jenv)->SetLongField(jenv, ptr->obj, pf->id, jv.j);
2376
+ }
2377
+ break;
2378
+ case 'I':
2379
+ if (pf->static_field)
2380
+ {
2381
+ (*jenv)->SetStaticIntField(jenv, ptr->klass, pf->id, jv.i);
2382
+ }
2383
+ else
2384
+ {
2385
+ (*jenv)->SetIntField(jenv, ptr->obj, pf->id, jv.i);
2386
+ }
2387
+ break;
2388
+ default:
2389
+ if (pf->static_field)
2390
+ {
2391
+ (*jenv)->SetStaticObjectField(jenv, ptr->klass, pf->id, jv.l);
2392
+ }
2393
+ else
2394
+ {
2395
+ (*jenv)->SetObjectField(jenv, ptr->obj, pf->id, jv.l);
2396
+ }
2397
+ break;
2398
+ }
2399
+ pf->arg_convert(jenv, val, &jv, pf->field_signature, 1);
2400
+ }
2401
+
2402
+ static VALUE invoke(JNIEnv* jenv, struct cls_method* pm, struct jvi_data* ptr,
2403
+ int argc, VALUE* argv, const char* sig)
2404
+ {
2405
+ int i, found;
2406
+ jvalue jv;
2407
+ jvalue* args;
2408
+ char* psig;
2409
+ struct cls_method* orgpm = pm;
2410
+
2411
+ for (found = 0; pm; pm = pm->next)
2412
+ {
2413
+ if (argc == pm->basic.arg_count)
2414
+ {
2415
+ if (sig)
2416
+ {
2417
+ if (!strcmp(sig, pm->basic.method_signature))
2418
+ {
2419
+ found = 1;
2420
+ break;
2421
+ }
2422
+ }
2423
+ else
2424
+ {
2425
+ psig = pm->basic.method_signature;
2426
+ found = 1;
2427
+ for (i = 0; i < argc; i++)
2428
+ {
2429
+ if (!check_rtype(jenv, *(argv + i), psig))
2430
+ {
2431
+ found = 0;
2432
+ break;
2433
+ }
2434
+ psig = next_sig(psig);
2435
+ }
2436
+ if (found) break;
2437
+ }
2438
+ }
2439
+ }
2440
+ if (!found)
2441
+ {
2442
+ char* tname = rb_id2name(orgpm->name);
2443
+ if (sig)
2444
+ {
2445
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s(\'%s\')'", tname, sig);
2446
+ }
2447
+ else
2448
+ {
2449
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
2450
+ }
2451
+ }
2452
+ args = (argc) ? ALLOCA_N(jvalue, argc) : NULL;
2453
+ psig = pm->basic.method_signature;
2454
+ for (i = 0; i < argc; i++)
2455
+ {
2456
+ R2J pr2j = *(pm->basic.arg_convert + i);
2457
+ pr2j(jenv, argv[i], args + i, psig, 0);
2458
+ psig = next_sig(psig);
2459
+ }
2460
+ switch (pm->basic.result_signature)
2461
+ {
2462
+ case 'D':
2463
+ {
2464
+ INVOKEAD voked = *(INVOKEAD*)(((char*)*jenv) + pm->method);
2465
+ jv.d = voked(jenv, ptr->obj, pm->basic.id, args);
2466
+ }
2467
+ break;
2468
+ case 'Z':
2469
+ case 'B':
2470
+ {
2471
+ INVOKEAZ vokez = *(INVOKEAZ*)(((char*)*jenv) + pm->method);
2472
+ jv.z = vokez(jenv, ptr->obj, pm->basic.id, args);
2473
+ }
2474
+ break;
2475
+ case 'F':
2476
+ {
2477
+ INVOKEAF vokef = *(INVOKEAF*)(((char*)*jenv) + pm->method);
2478
+ jv.f = vokef(jenv, ptr->obj, pm->basic.id, args);
2479
+ }
2480
+ break;
2481
+ case 'C':
2482
+ case 'S':
2483
+ {
2484
+ INVOKEAS vokes = *(INVOKEAS*)(((char*)*jenv) + pm->method);
2485
+ jv.s = vokes(jenv, ptr->obj, pm->basic.id, args);
2486
+ }
2487
+ break;
2488
+ #if HAVE_LONG_LONG
2489
+ case 'J':
2490
+ {
2491
+ INVOKEAL vokel = *(INVOKEAL*)(((char*)*jenv) + pm->method);
2492
+ jv.j = vokel(jenv, ptr->obj, pm->basic.id, args);
2493
+ }
2494
+ break;
2495
+ #endif
2496
+ default:
2497
+ {
2498
+ INVOKEA voke = *(INVOKEA*)(((char*)*jenv) + pm->method);
2499
+ jv.l = voke(jenv, ptr->obj, pm->basic.id, args);
2500
+ }
2501
+ break;
2502
+ }
2503
+ rjb_check_exception(jenv, 1);
2504
+ psig = pm->basic.method_signature;
2505
+ for (i = 0; i < argc; i++)
2506
+ {
2507
+ R2J pr2j = *(pm->basic.arg_convert + i);
2508
+ pr2j(jenv, argv[i], args + i, psig, 1);
2509
+ psig = next_sig(psig);
2510
+ }
2511
+ if (pm->basic.result_arraydepth)
2512
+ {
2513
+ return ja2r(pm->result_convert, jenv, jv, pm->basic.result_arraydepth);
2514
+ }
2515
+ else
2516
+ {
2517
+ return pm->result_convert(jenv, jv);
2518
+ }
2519
+ }
2520
+
2521
+ /*
2522
+ * Object invocation
2523
+ */
2524
+ static VALUE invoke_by_instance(ID rmid, int argc, VALUE* argv,
2525
+ struct jvi_data* ptr, char* sig)
2526
+ {
2527
+ VALUE ret = Qnil;
2528
+ JNIEnv* jenv = rjb_attach_current_thread();
2529
+ struct cls_field* pf;
2530
+ struct cls_method* pm;
2531
+ char* tname = rb_id2name(rmid);
2532
+
2533
+ if (argc == 0 && st_lookup(ptr->fields, rmid, (st_data_t*)&pf))
2534
+ {
2535
+ ret = getter(jenv, pf, ptr);
2536
+ }
2537
+ else if (argc == 1 && *(tname + strlen(tname) - 1) == '=')
2538
+ {
2539
+ char* fname = ALLOCA_N(char, strlen(tname) + 1);
2540
+ strcpy(fname, tname);
2541
+ fname[strlen(tname) - 1] = '\0';
2542
+ if (st_lookup(ptr->fields, rb_intern(fname), (st_data_t*)&pf))
2543
+ {
2544
+ setter(jenv, pf, ptr, *argv);
2545
+ return ret;
2546
+ }
2547
+ // fall through for the setter alias name
2548
+ }
2549
+ if (st_lookup(ptr->methods, rmid, (st_data_t*)&pm))
2550
+ {
2551
+ ret = invoke(jenv, pm, ptr, argc, argv, sig);
2552
+ }
2553
+ else
2554
+ {
2555
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
2556
+ }
2557
+ return ret;
2558
+ }
2559
+
2560
+ static VALUE rjb_i_invoke(int argc, VALUE* argv, VALUE self)
2561
+ {
2562
+ VALUE vsig, rmid, rest;
2563
+ char* sig;
2564
+ struct jvi_data* ptr;
2565
+
2566
+ rb_scan_args(argc, argv, "2*", &rmid, &vsig, &rest);
2567
+ rmid = rb_to_id(rmid);
2568
+ sig = StringValueCStr(vsig);
2569
+ Data_Get_Struct(self, struct jvi_data, ptr);
2570
+
2571
+ return invoke_by_instance(rmid, argc -2, argv + 2, ptr, sig);
2572
+ }
2573
+
2574
+ static VALUE rjb_i_missing(int argc, VALUE* argv, VALUE self)
2575
+ {
2576
+ struct jvi_data* ptr;
2577
+ ID rmid = rb_to_id(argv[0]);
2578
+
2579
+ Data_Get_Struct(self, struct jvi_data, ptr);
2580
+
2581
+ return invoke_by_instance(rmid, argc -1, argv + 1, ptr, NULL);
2582
+ }
2583
+
2584
+ /*
2585
+ * Class invocation (first static method, then instance method)
2586
+ */
2587
+ static VALUE invoke_by_class(ID rmid, int argc, VALUE* argv,
2588
+ struct jv_data* ptr, char* sig)
2589
+ {
2590
+ VALUE ret = Qnil;
2591
+ struct jv_data* clsptr;
2592
+ struct cls_field* pf;
2593
+ struct cls_method* pm;
2594
+ char* tname = rb_id2name(rmid);
2595
+ JNIEnv* jenv = rjb_attach_current_thread();
2596
+
2597
+ Data_Get_Struct(jklass, struct jv_data, clsptr);
2598
+ if (argc == 0 && st_lookup(ptr->idata.fields, rmid, (st_data_t*)&pf))
2599
+ {
2600
+ if (!pf->static_field)
2601
+ {
2602
+ rb_raise(rb_eRuntimeError, "instance field `%s' for class", tname);
2603
+ }
2604
+ ret = getter(jenv, pf, &ptr->idata);
2605
+ }
2606
+ else if (argc == 1 && *(tname + strlen(tname) - 1) == '=')
2607
+ {
2608
+ char* fname = ALLOCA_N(char, strlen(tname) + 1);
2609
+ strcpy(fname, tname);
2610
+ fname[strlen(tname) - 1] = '\0';
2611
+ if (st_lookup(ptr->idata.fields, rb_intern(fname), (st_data_t*)&pf))
2612
+ {
2613
+ if (!pf->static_field)
2614
+ {
2615
+ rb_raise(rb_eRuntimeError, "instance field `%s' for class", fname);
2616
+ }
2617
+ setter(jenv, pf, &ptr->idata, *argv);
2618
+ }
2619
+ else
2620
+ {
2621
+ rb_raise(rb_eRuntimeError, "Fail: unknown field name `%s'", fname);
2622
+ }
2623
+ }
2624
+ else if (st_lookup(ptr->static_methods, rmid, (st_data_t*)&pm))
2625
+ {
2626
+ ret = invoke(jenv, pm, &ptr->idata, argc, argv, sig);
2627
+ }
2628
+ else if (st_lookup(clsptr->idata.methods, rmid, (st_data_t*)&pm))
2629
+ {
2630
+ ret = invoke(jenv, pm, &ptr->idata, argc, argv, sig);
2631
+ }
2632
+ else
2633
+ {
2634
+ if (st_lookup(ptr->idata.methods, rmid, (st_data_t*)&pm))
2635
+ {
2636
+ rb_raise(rb_eRuntimeError, "instance method `%s' for class", tname);
2637
+ }
2638
+ else
2639
+ {
2640
+ rb_raise(rb_eRuntimeError, "Fail: unknown method name `%s'", tname);
2641
+ }
2642
+ }
2643
+
2644
+ return ret;
2645
+ }
2646
+
2647
+ static VALUE rjb_invoke(int argc, VALUE* argv, VALUE self)
2648
+ {
2649
+ VALUE vsig, rmid, rest;
2650
+ char* sig;
2651
+ struct jv_data* ptr;
2652
+
2653
+ rb_scan_args(argc, argv, "2*", &rmid, &vsig, &rest);
2654
+ rmid = rb_to_id(rmid);
2655
+ sig = StringValueCStr(vsig);
2656
+ Data_Get_Struct(self, struct jv_data, ptr);
2657
+
2658
+ return invoke_by_class(rmid, argc - 2, argv + 2, ptr, sig);
2659
+ }
2660
+
2661
+ static VALUE find_const(VALUE pv)
2662
+ {
2663
+ VALUE* p = (VALUE*)pv;
2664
+ return rb_const_get(*p, (ID)*(p + 1));
2665
+ }
2666
+
2667
+ static VALUE rjb_missing(int argc, VALUE* argv, VALUE self)
2668
+ {
2669
+ struct jv_data* ptr;
2670
+ ID rmid = rb_to_id(argv[0]);
2671
+ char* rmname = rb_id2name(rmid);
2672
+ if (isupper(*rmname))
2673
+ {
2674
+ VALUE r, args[2];
2675
+ int state = 0;
2676
+ args[0] = RBASIC(self)->klass;
2677
+ args[1] = rmid;
2678
+ r = rb_protect(find_const, (VALUE)args, &state);
2679
+ if (!state)
2680
+ {
2681
+ return r;
2682
+ }
2683
+ }
2684
+
2685
+ Data_Get_Struct(self, struct jv_data, ptr);
2686
+ return invoke_by_class(rmid, argc - 1, argv + 1, ptr, NULL);
2687
+ }
2688
+
2689
+ /*
2690
+ * Class#forName entry.
2691
+ */
2692
+ static VALUE rjb_class_forname(int argc, VALUE* argv, VALUE self)
2693
+ {
2694
+ if (argc == 1)
2695
+ {
2696
+ return rjb_s_import(self, *argv);
2697
+ }
2698
+ else
2699
+ {
2700
+ struct jv_data* ptr;
2701
+ ID rmid = rb_intern("forName");
2702
+ Data_Get_Struct(self, struct jv_data, ptr);
2703
+ return invoke_by_class(rmid, argc, argv, ptr, NULL);
2704
+ }
2705
+ }
2706
+
2707
+ /*
2708
+ * Class initializer called by Ruby while requiring this library
2709
+ */
2710
+ void Init_rjbcore()
2711
+ {
2712
+ rb_protect((VALUE(*)(VALUE))rb_require, (VALUE)"iconv", NULL);
2713
+
2714
+ rjb_loaded_classes = rb_hash_new();
2715
+ OBJ_FREEZE(rjb_loaded_classes);
2716
+ rb_global_variable(&rjb_loaded_classes);
2717
+ proxies = rb_ary_new();
2718
+ rb_global_variable(&proxies);
2719
+
2720
+ rjb = rb_define_module("Rjb");
2721
+ rb_define_module_function(rjb, "load", rjb_s_load, -1);
2722
+ rb_define_module_function(rjb, "unload", rjb_s_unload, -1);
2723
+ rb_define_module_function(rjb, "import", rjb_s_import, 1);
2724
+ rb_define_module_function(rjb, "bind", rjb_s_bind, 2);
2725
+ rb_define_module_function(rjb, "classes", rjb_s_classes, 0);
2726
+ rb_define_module_function(rjb, "throw", rjb_s_throw, -1);
2727
+ rb_define_module_function(rjb, "primitive_conversion=", rjb_s_set_pconversion, 1);
2728
+ rb_define_module_function(rjb, "primitive_conversion", rjb_s_get_pconversion, 0);
2729
+ rb_define_const(rjb, "VERSION", rb_str_new2(RJB_VERSION));
2730
+
2731
+ /* Java class object */
2732
+ rjbc = rb_class_new(rb_cObject);
2733
+ rb_gc_register_address(&rjbc);
2734
+ rb_define_method(rjbc, "method_missing", rjb_missing, -1);
2735
+ rb_define_method(rjbc, "_invoke", rjb_invoke, -1);
2736
+ rb_define_method(rjbc, "_classname", rjb_i_class, 0);
2737
+
2738
+ /* Java instance object */
2739
+ rjbi = rb_class_new(rb_cObject);
2740
+ rb_gc_register_address(&rjbi);
2741
+ rb_define_method(rjbi, "method_missing", rjb_i_missing, -1);
2742
+ rb_define_method(rjbi, "_invoke", rjb_i_invoke, -1);
2743
+ rb_define_method(rjbi, "_classname", rjb_i_class, 0);
2744
+
2745
+ /* Ruby-Java Bridge object */
2746
+ rjbb = rb_class_new(rb_cObject);
2747
+ rb_gc_register_address(&rjbb);
2748
+ }
2749
+
2750
+ static VALUE safe_funcall(VALUE args)
2751
+ {
2752
+ VALUE* argp = (VALUE*)args;
2753
+ return rb_funcall2(*argp, *(argp + 1), *(argp + 2), argp + 3);
2754
+ }
2755
+
2756
+ /**
2757
+ Entry point from JavaVM through java.reflect.Proxy
2758
+ */
2759
+ JNIEXPORT jobject JNICALL Java_jp_co_infoseek_hp_arton_rjb_RBridge_call
2760
+ (JNIEnv * jenv, jobject bridge, jstring name, jobject proxy, jobjectArray args)
2761
+ {
2762
+ int i;
2763
+ jvalue j;
2764
+ memset(&j, 0, sizeof(j));
2765
+
2766
+ for (i = 0; i < RARRAY_LEN(proxies); i++)
2767
+ {
2768
+ struct rj_bridge* ptr;
2769
+ VALUE val = RARRAY_PTR(proxies)[i];
2770
+ Data_Get_Struct(val, struct rj_bridge, ptr);
2771
+ if ((*jenv)->IsSameObject(jenv, proxy, ptr->proxy))
2772
+ {
2773
+ int sstat;
2774
+ VALUE result;
2775
+ VALUE* argv = NULL;
2776
+ int argc = 3;
2777
+ ID id = rb_to_id(jstring2val(jenv, name));
2778
+ if (args)
2779
+ {
2780
+ int i;
2781
+ jsize js = (*jenv)->GetArrayLength(jenv, args);
2782
+ argc += (int)js;
2783
+ argv = ALLOCA_N(VALUE, argc);
2784
+ memset(argv, 0, sizeof(VALUE*) * argc);
2785
+ for (i = 3; i < argc; i++)
2786
+ {
2787
+ jobject f = (*jenv)->GetObjectArrayElement(jenv, args, i - 3);
2788
+ /* f will be release in jv2rv_withprim */
2789
+ *(argv + i) = jv2rv_withprim(jenv, f);
2790
+ }
2791
+ }
2792
+ else
2793
+ {
2794
+ argv = ALLOCA_N(VALUE, argc + 1);
2795
+ memset(argv, 0, sizeof(VALUE*) * (argc + 1));
2796
+ }
2797
+ *argv = ptr->wrapped;
2798
+ *(argv + 1) = id;
2799
+ *(argv + 2) = argc - 3;
2800
+ result = rb_protect(safe_funcall, (VALUE)argv, &sstat);
2801
+ rv2jobject(jenv, result, &j, NULL, 0);
2802
+ // I can't delete this object...
2803
+ break;
2804
+ }
2805
+ }
2806
+ return j.l;
2807
+ }