php_vm 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/php_vm/php_vm.c +114 -12
- data/ext/php_vm/php_vm.h +5 -0
- metadata +1 -1
data/ext/php_vm/php_vm.c
CHANGED
@@ -160,9 +160,41 @@ int new_php_object(zend_class_entry *ce, VALUE v_args, zval *retval)
|
|
160
160
|
return result;
|
161
161
|
}
|
162
162
|
|
163
|
+
void define_php_properties(VALUE v_obj, zend_class_entry *ce, int is_static)
|
164
|
+
{
|
165
|
+
HashPosition pos;
|
166
|
+
zend_property_info *prop;
|
167
|
+
|
168
|
+
zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
|
169
|
+
|
170
|
+
while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
|
171
|
+
int flag = prop->flags;
|
172
|
+
const char *getter_name = prop->name;
|
173
|
+
char *setter_name = malloc(prop->name_length+ 1);
|
174
|
+
sprintf(setter_name, "%s=", getter_name);
|
175
|
+
|
176
|
+
if (is_static) {
|
177
|
+
// static variable
|
178
|
+
if (0<(flag & ZEND_ACC_STATIC)) {
|
179
|
+
rb_define_singleton_method(v_obj, getter_name, rb_php_class_getter, 0);
|
180
|
+
rb_define_singleton_method(v_obj, setter_name, rb_php_class_setter, 1);
|
181
|
+
}
|
182
|
+
} else {
|
183
|
+
// instance variable
|
184
|
+
if (0==(flag & ZEND_ACC_STATIC)) {
|
185
|
+
rb_define_singleton_method(v_obj, getter_name, rb_php_object_getter, 0);
|
186
|
+
rb_define_singleton_method(v_obj, setter_name, rb_php_object_setter, 1);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
free(setter_name);
|
191
|
+
zend_hash_move_forward_ex(&ce->properties_info, &pos);
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
163
195
|
void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static)
|
164
196
|
{
|
165
|
-
// TODO: access
|
197
|
+
// TODO: access scope
|
166
198
|
// TODO: __toString
|
167
199
|
// TODO: __clone
|
168
200
|
// TODO: __call
|
@@ -184,6 +216,7 @@ void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static)
|
|
184
216
|
// class method
|
185
217
|
if (strcmp("new", fname)==0) {
|
186
218
|
// new => no define
|
219
|
+
|
187
220
|
} else if (0<(flag & ZEND_ACC_STATIC)) {
|
188
221
|
// other method
|
189
222
|
rb_define_singleton_method(v_obj, fname, rb_php_class_call, -1);
|
@@ -258,15 +291,16 @@ int call_php_method(zend_class_entry *ce, zval *obj, zend_function *mptr, int ar
|
|
258
291
|
|
259
292
|
// Ruby
|
260
293
|
|
294
|
+
VALUE backtrace_re;
|
295
|
+
|
261
296
|
VALUE get_callee_name()
|
262
297
|
{
|
263
298
|
VALUE backtrace_arr = rb_funcall(rb_mKernel, rb_intern("caller"), 1, INT2NUM(0));
|
264
299
|
if (backtrace_arr) {
|
265
300
|
VALUE backtrace = rb_funcall(backtrace_arr, rb_intern("first"), 0);
|
266
301
|
if (backtrace) {
|
267
|
-
VALUE
|
268
|
-
|
269
|
-
if (m) {
|
302
|
+
VALUE m = rb_funcall(backtrace, rb_intern("match"), 1, backtrace_re);
|
303
|
+
if (m!=Qnil) {
|
270
304
|
return rb_funcall(m, rb_intern("[]"), 1, INT2NUM(3));
|
271
305
|
}
|
272
306
|
}
|
@@ -287,16 +321,50 @@ VALUE call_php_method_bridge(zend_class_entry *ce, zval *obj, VALUE callee, int
|
|
287
321
|
find_zend_function(ce, RSTRING_PTR(callee), RSTRING_LEN(callee), &mptr);
|
288
322
|
|
289
323
|
// call
|
290
|
-
zval *
|
291
|
-
|
324
|
+
zval *z_val;
|
325
|
+
if (mptr) {
|
326
|
+
// call method
|
327
|
+
int result = call_php_method(ce, obj, mptr, argc, argv, &z_val TSRMLS_CC);
|
292
328
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
329
|
+
// exception
|
330
|
+
if (result==FAILURE) {
|
331
|
+
char *message = malloc(32+RSTRING_LEN(callee));
|
332
|
+
sprintf(message, "raise exception: %s", RSTRING_PTR(callee));
|
333
|
+
VALUE exception = rb_exc_new2(rb_ePHPError, message);
|
334
|
+
free(message);
|
335
|
+
rb_exc_raise(exception);
|
336
|
+
}
|
337
|
+
} else {
|
338
|
+
VALUE is_setter = rb_funcall(callee, rb_intern("end_with?"), 1, rb_str_new2("="));
|
339
|
+
|
340
|
+
if (is_setter) {
|
341
|
+
// setter
|
342
|
+
rb_funcall(callee, rb_intern("gsub!"), 2, rb_str_new2("="), rb_str_new2(""));
|
343
|
+
MAKE_STD_ZVAL(z_val);
|
344
|
+
value_to_zval(argv[0], z_val);
|
345
|
+
|
346
|
+
if (obj) {
|
347
|
+
// instance
|
348
|
+
add_property_zval(obj, RSTRING_PTR(callee), z_val);
|
349
|
+
} else {
|
350
|
+
// static
|
351
|
+
zend_update_static_property(ce, RSTRING_PTR(callee), RSTRING_LEN(callee), z_val TSRMLS_CC);
|
352
|
+
}
|
353
|
+
|
354
|
+
return Qnil;
|
355
|
+
} else {
|
356
|
+
// getter
|
357
|
+
if (obj) {
|
358
|
+
// instance
|
359
|
+
z_val = zend_read_property(ce, obj, RSTRING_PTR(callee), RSTRING_LEN(callee), 0 TSRMLS_CC);
|
360
|
+
} else {
|
361
|
+
// static
|
362
|
+
z_val = zend_read_static_property(ce, RSTRING_PTR(callee), RSTRING_LEN(callee), 0 TSRMLS_CC);
|
363
|
+
}
|
364
|
+
}
|
297
365
|
}
|
298
366
|
|
299
|
-
return zval_to_value(
|
367
|
+
return zval_to_value(z_val);
|
300
368
|
}
|
301
369
|
|
302
370
|
|
@@ -426,6 +494,7 @@ VALUE rb_php_class_initialize(VALUE self, VALUE v_name)
|
|
426
494
|
rb_iv_set(self, "php_native_resource", resource);
|
427
495
|
|
428
496
|
// define php static methods
|
497
|
+
define_php_properties(self, *ce, 1);
|
429
498
|
define_php_methods(self, *ce, 1);
|
430
499
|
|
431
500
|
return self;
|
@@ -451,11 +520,26 @@ VALUE rb_php_class_new(int argc, VALUE *argv, VALUE self)
|
|
451
520
|
rb_php_object_initialize(obj, self, args);
|
452
521
|
|
453
522
|
// define php instance method
|
523
|
+
define_php_properties(obj, ce, 0);
|
454
524
|
define_php_methods(obj, ce, 0);
|
455
525
|
|
456
526
|
return obj;
|
457
527
|
}
|
458
528
|
|
529
|
+
VALUE rb_php_class_getter(VALUE self)
|
530
|
+
{
|
531
|
+
zend_class_entry *ce = get_zend_class_entry(self);
|
532
|
+
VALUE callee = get_callee_name();
|
533
|
+
return call_php_method_bridge(ce, NULL, callee, 0, NULL);
|
534
|
+
}
|
535
|
+
|
536
|
+
VALUE rb_php_class_setter(VALUE self, VALUE value)
|
537
|
+
{
|
538
|
+
zend_class_entry *ce = get_zend_class_entry(self);
|
539
|
+
VALUE callee = get_callee_name();
|
540
|
+
return call_php_method_bridge(ce, NULL, callee, 1, &value);
|
541
|
+
}
|
542
|
+
|
459
543
|
VALUE rb_php_class_call(int argc, VALUE *argv, VALUE self)
|
460
544
|
{
|
461
545
|
zend_class_entry *ce = get_zend_class_entry(self);
|
@@ -492,6 +576,22 @@ VALUE rb_php_object_php_class(VALUE self)
|
|
492
576
|
return rb_iv_get(self, "php_class");
|
493
577
|
}
|
494
578
|
|
579
|
+
VALUE rb_php_object_getter(VALUE self)
|
580
|
+
{
|
581
|
+
zend_class_entry *ce = get_zend_class_entry(self);
|
582
|
+
zval *zobj = get_zval(self);
|
583
|
+
VALUE callee = get_callee_name();
|
584
|
+
return call_php_method_bridge(ce, zobj, callee, 0, NULL);
|
585
|
+
}
|
586
|
+
|
587
|
+
VALUE rb_php_object_setter(VALUE self, VALUE value)
|
588
|
+
{
|
589
|
+
zend_class_entry *ce = get_zend_class_entry(self);
|
590
|
+
zval *zobj = get_zval(self);
|
591
|
+
VALUE callee = get_callee_name();
|
592
|
+
return call_php_method_bridge(ce, zobj, callee, 1, &value);
|
593
|
+
}
|
594
|
+
|
495
595
|
VALUE rb_php_object_call(int argc, VALUE *argv, VALUE self)
|
496
596
|
{
|
497
597
|
zend_class_entry *ce = get_zend_class_entry(self);
|
@@ -531,6 +631,8 @@ void Init_php_vm()
|
|
531
631
|
php_vm_module_init();
|
532
632
|
atexit(php_vm_module_exit);
|
533
633
|
|
634
|
+
backtrace_re = rb_funcall(rb_cRegexp, rb_intern("new"), 1, rb_str_new2("^(.+?):(\\d+)(?::in `(.*)')?"));
|
635
|
+
|
534
636
|
// module PHPVM
|
535
637
|
rb_mPHPVM = rb_define_module("PHPVM");
|
536
638
|
|
@@ -539,7 +641,7 @@ void Init_php_vm()
|
|
539
641
|
rb_define_singleton_method(rb_mPHPVM, "exec", rb_php_vm_exec, 1);
|
540
642
|
rb_define_singleton_method(rb_mPHPVM, "getClass", rb_php_vm_getClass, 1);
|
541
643
|
|
542
|
-
rb_define_const(rb_mPHPVM, "VERSION", rb_str_new2("1.0
|
644
|
+
rb_define_const(rb_mPHPVM, "VERSION", rb_str_new2("1.1.0"));
|
543
645
|
|
544
646
|
// class PHPVM::PHPClass
|
545
647
|
rb_cPHPClass = rb_define_class_under(rb_mPHPVM, "PHPClass", rb_cObject);
|
data/ext/php_vm/php_vm.h
CHANGED
@@ -27,6 +27,7 @@ extern void find_zend_class_entry2(char *name, zend_class_entry ***ce);
|
|
27
27
|
extern int is_exception_zend_class_entry(zend_class_entry *ce TSRMLS_DC);
|
28
28
|
extern int is_exception_zval(zval *z TSRMLS_DC);
|
29
29
|
extern int new_php_object(zend_class_entry *ce, VALUE v_args, zval *retval);
|
30
|
+
extern void define_php_properties(VALUE v_obj, zend_class_entry *ce, int is_static);
|
30
31
|
extern void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static);
|
31
32
|
extern int call_php_method(zend_class_entry *ce, zval *obj, zend_function *mptr, int argc, VALUE *v_argv, zval **retval_ptr TSRMLS_DC);
|
32
33
|
|
@@ -49,11 +50,15 @@ extern VALUE rb_php_class_get(VALUE cls, VALUE rbv_name);
|
|
49
50
|
extern VALUE rb_php_class_initialize(VALUE self, VALUE rbv_name);
|
50
51
|
extern VALUE rb_php_class_name(VALUE self);
|
51
52
|
extern VALUE rb_php_class_new(int argc, VALUE *argv, VALUE self);
|
53
|
+
extern VALUE rb_php_class_getter(VALUE self);
|
54
|
+
extern VALUE rb_php_class_setter(VALUE self, VALUE value);
|
52
55
|
extern VALUE rb_php_class_call(int argc, VALUE *argv, VALUE self);
|
53
56
|
|
54
57
|
// class PHPVM::PHPObject
|
55
58
|
extern VALUE rb_php_object_initialize(VALUE self, VALUE class, VALUE arg_arr);
|
56
59
|
extern VALUE rb_php_object_php_class(VALUE self);
|
60
|
+
extern VALUE rb_php_object_getter(VALUE self);
|
61
|
+
extern VALUE rb_php_object_setter(VALUE self, VALUE value);
|
57
62
|
extern VALUE rb_php_object_call(int argc, VALUE *argv, VALUE self);
|
58
63
|
|
59
64
|
// module
|