php_vm 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|