Call php method via function name instead of calling directly.

This changes the linking error if php extension is not statically linked
to a runtime error. In this way, users who don't need Timestamp can
still use protobuf even if date extension is not statically linked in
php.
pull/4034/head
Bo Yang 7 years ago
parent 88102eae8f
commit fffe8d39f8
  1. 70
      php/ext/google/protobuf/message.c
  2. 4
      php/ext/google/protobuf/protobuf.h
  3. 8
      php/tests/memory_leak_test.php
  4. 2
      php/tests/test.sh

@ -31,10 +31,6 @@
#include <php.h>
#include <stdlib.h>
#ifdef PROTOBUF_ENABLE_TIMESTAMP
#include <ext/date/php_date.h>
#endif
#include "protobuf.h"
#include "utf8.h"
@ -1124,7 +1120,6 @@ PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Seconds, "seconds")
PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Nanos, "nanos")
PHP_METHOD(Timestamp, fromDateTime) {
#ifdef PROTOBUF_ENABLE_TIMESTAMP
zval* datetime;
zval member;
@ -1134,23 +1129,27 @@ PHP_METHOD(Timestamp, fromDateTime) {
}
// Get timestamp from Datetime object.
zval* retval_ptr;
zval* function_name;
zval retval;
zval function_name;
int64_t timestamp;
MAKE_STD_ZVAL(retval_ptr);
MAKE_STD_ZVAL(function_name);
#if PHP_MAJOR_VERSION < 7
INIT_ZVAL(retval);
INIT_ZVAL(function_name);
#endif
ZVAL_STRING(function_name, "date_timestamp_get", 1);
PHP_PROTO_ZVAL_STRING(&function_name, "date_timestamp_get", 1);
if (call_user_function(EG(function_table), NULL,
function_name, retval_ptr, 1,
&datetime TSRMLS_CC) == SUCCESS) {
protobuf_convert_to_int64(retval_ptr, &timestamp);
if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
ZVAL_PTR_TO_CACHED_PTR(datetime) TSRMLS_CC) == FAILURE) {
zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
return;
}
zval_ptr_dtor(&retval_ptr);
zval_ptr_dtor(&function_name);
protobuf_convert_to_int64(&retval, &timestamp);
zval_dtor(&retval);
zval_dtor(&function_name);
// Set seconds
MessageHeader* self = UNBOX(MessageHeader, getThis());
@ -1167,17 +1166,9 @@ PHP_METHOD(Timestamp, fromDateTime) {
*(int32_t*)memory = 0;
RETURN_NULL();
#else
zend_error(E_USER_ERROR, "fromDateTime needs date extension.");
#endif
}
PHP_METHOD(Timestamp, toDateTime) {
#ifdef PROTOBUF_ENABLE_TIMESTAMP
zval datetime;
php_date_instantiate(php_date_get_date_ce(), &datetime TSRMLS_CC);
php_date_obj* dateobj = UNBOX(php_date_obj, &datetime);
// Get seconds
MessageHeader* self = UNBOX(MessageHeader, getThis());
const upb_fielddef* field =
@ -1198,16 +1189,37 @@ PHP_METHOD(Timestamp, toDateTime) {
strftime(formated_time, sizeof(formated_time), "%Y-%m-%dT%H:%M:%SUTC",
utc_time);
if (!php_date_initialize(dateobj, formated_time, strlen(formated_time), NULL,
NULL, 0 TSRMLS_CC)) {
zval_dtor(&datetime);
RETURN_NULL();
// Create Datetime object.
zval datetime;
zval formated_time_php;
zval function_name;
int64_t timestamp = 0;
#if PHP_MAJOR_VERSION < 7
INIT_ZVAL(function_name);
INIT_ZVAL(formated_time_php);
#endif
PHP_PROTO_ZVAL_STRING(&function_name, "date_create", 1);
PHP_PROTO_ZVAL_STRING(&formated_time_php, formated_time, 1);
CACHED_VALUE params[1] = {ZVAL_TO_CACHED_VALUE(formated_time_php)};
if (call_user_function(EG(function_table), NULL,
&function_name, &datetime, 1,
params TSRMLS_CC) == FAILURE) {
zend_error(E_ERROR, "Cannot create DateTime.");
return;
}
zval_dtor(&formated_time_php);
zval_dtor(&function_name);
#if PHP_MAJOR_VERSION < 7
zval* datetime_ptr = &datetime;
PHP_PROTO_RETVAL_ZVAL(datetime_ptr);
#else
zend_error(E_USER_ERROR, "toDateTime needs date extension.");
ZVAL_OBJ(return_value, Z_OBJ(datetime));
#endif
}

@ -182,6 +182,8 @@
#define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (VALUE)
#define ZVAL_TO_CACHED_VALUE(VALUE) (&VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
@ -452,6 +454,8 @@ static inline int php_proto_zend_hash_get_current_data_ex(HashTable* ht,
#define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
#define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
#define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (*VALUE)
#define ZVAL_TO_CACHED_VALUE(VALUE) (VALUE)
#define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));

@ -131,12 +131,12 @@ $timestamp = new \Google\Protobuf\Timestamp();
date_default_timezone_set('UTC');
$from = new DateTime('2011-01-01T15:03:01.012345UTC');
$timestamp->fromDateTime($from);
assert($from->format('U'), $timestamp->getSeconds());
assert(0, $timestamp->getNanos());
assert($from->format('U') == $timestamp->getSeconds());
assert(0 == $timestamp->getNanos());
$to = $timestamp->toDateTime();
assert(\DateTime::class, get_class($to));
assert($from->format('U'), $to->format('U'));
assert(\DateTime::class == get_class($to));
assert($from->format('U') == $to->format('U'));
$from = new \Google\Protobuf\Value();
$from->setNumberValue(1);

@ -5,7 +5,7 @@ pushd ../ext/google/protobuf/
make clean || true
set -e
# Add following in configure for debug: --enable-debug CFLAGS='-g -O0'
phpize && ./configure CFLAGS='-g -O0 -DPROTOBUF_ENABLE_TIMESTAMP' && make
phpize && ./configure CFLAGS='-g -O0' && make
popd
tests=( array_test.php encode_decode_test.php generated_class_test.php generated_phpdoc_test.php map_field_test.php well_known_test.php generated_service_test.php descriptors_test.php )

Loading…
Cancel
Save