rjb 1.1.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }