// extern void TF_SetAttrTypeList(TF_OperationDescription* desc, // const char* attr_name, const TF_DataType* values, // int num_values); static PHP_METHOD(TensorFlow_OperationDescription, setAttrTypeList) { zend_string *name; zval* dtypes; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STR(name) Z_PARAM_ARRAY(dtypes) ZEND_PARSE_PARAMETERS_END(); TF_DataType* tf_values = NULL; int tf_num_values = 0; HashTable *values_table = Z_ARRVAL_P(dtypes); tf_num_values = zend_hash_num_elements(values_table); // count of array if (tf_num_values > 0) { tf_values = (TF_DataType*)emalloc(sizeof(TF_DataType) * tf_num_values); HashPosition pos; zval* element; int index = 0; zend_hash_internal_pointer_reset_ex(values_table, &pos); while (zend_hash_has_more_elements_ex(values_table, &pos) == SUCCESS) { if (!(element = zend_hash_get_current_data_ex(values_table, &pos))) { zend_throw_exception(spl_ce_InvalidArgumentException, "dtypes something wrong", 0); return; } if (zval_get_type(element) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "dtypes must be array of integer", 0); return; } if (!valid_dtype(Z_LVAL_P(element))) { zend_throw_exception(spl_ce_InvalidArgumentException, "each dtype must be from 1 to 20", 0); return; } // insert tf_values tf_values[index] = Z_LVAL_P(element); // php_printf("%d \n", element->value.lval); zend_hash_move_forward_ex(values_table, &pos); index++; } } // int i; // for (i = 0; i < tf_num_values; i++) { // php_printf("dtypes[%d] ? %d\n", i, tf_values[i]); // } // php_printf("tf_num_values ? %d\n", tf_num_values); // this t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); t_tf_operation_description* node = intern->ptr; TF_SetAttrTypeList(node->src, name->val, tf_values, tf_num_values); }
/** * Construct an instance of the Channel class. If the $args array contains a * "credentials" key mapping to a ChannelCredentials object, a secure channel * will be created with those credentials. * @param string $target The hostname to associate with this channel * @param array $args The arguments to pass to the Channel (optional) */ PHP_METHOD(Channel, __construct) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); zend_string *target; zval *args_array = NULL; grpc_channel_args args; HashTable *array_hash; zval *creds_obj = NULL; wrapped_grpc_channel_credentials *creds = NULL; /* "Sa" == 1 string, 1 array */ #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sa", &target, &args_array) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "Channel expects a string and an array", 1); return; } #else ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STR(target) Z_PARAM_ARRAY(args_array) ZEND_PARSE_PARAMETERS_END(); #endif array_hash = HASH_OF(args_array); if ((creds_obj = zend_hash_str_find(array_hash, "credentials", sizeof("credentials") - 1)) != NULL) { if (Z_TYPE_P(creds_obj) == IS_NULL) { creds = NULL; zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); } else if (Z_OBJ_P(creds_obj)->ce != grpc_ce_channel_credentials) { zend_throw_exception(spl_ce_InvalidArgumentException, "credentials must be a ChannelCredentials object", 1); return; } else { creds = Z_WRAPPED_GRPC_CHANNEL_CREDS_P(creds_obj); zend_hash_str_del(array_hash, "credentials", sizeof("credentials") - 1); } } php_grpc_read_args_array(args_array, &args); if (creds == NULL) { channel->wrapped = grpc_insecure_channel_create(ZSTR_VAL(target), &args, NULL); } else { channel->wrapped = grpc_secure_channel_create(creds->wrapped, ZSTR_VAL(target), &args, NULL); } efree(args.args); }
/** * Start a batch of RPC actions. * @param array batch Array of actions to take * @return object Object with results of all actions */ PHP_METHOD(Call, startBatch) { wrapped_grpc_call *call = Z_WRAPPED_GRPC_CALL_P(getThis()); grpc_op ops[8]; size_t op_num = 0; zval *array; zval *value; zval *inner_value; HashTable *array_hash; HashPosition array_pointer; HashTable *status_hash; HashTable *message_hash; zval *message_value; zval *message_flags; zend_string *key; zend_ulong index; grpc_metadata_array metadata; grpc_metadata_array trailing_metadata; grpc_metadata_array recv_metadata; grpc_metadata_array recv_trailing_metadata; grpc_status_code status; char *status_details = NULL; size_t status_details_capacity = 0; grpc_byte_buffer *message; int cancelled; grpc_call_error error; char *message_str; size_t message_len; zval recv_status; grpc_metadata_array_init(&metadata); grpc_metadata_array_init(&trailing_metadata); grpc_metadata_array_init(&recv_metadata); grpc_metadata_array_init(&recv_trailing_metadata); object_init(return_value); /* "a" == 1 array */ #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "start_batch expects an array", 1); goto cleanup; } #else ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_ARRAY(array) ZEND_PARSE_PARAMETERS_END(); #endif array_hash = HASH_OF(array); //TODO(thinkerou): why phpunit wrong when use ZEND_HASH_FOREACH_VAL marco? //ZEND_HASH_FOREACH_VAL(array_hash, value) { for (zend_hash_internal_pointer_reset_ex(array_hash, &array_pointer); (value = zend_hash_get_current_data_ex(array_hash, &array_pointer)) != NULL; zend_hash_move_forward_ex(array_hash, &array_pointer)) { if (zend_hash_get_current_key_ex(array_hash, &key, &index, &array_pointer) != HASH_KEY_IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "batch keys must be integers", 1); goto cleanup; } switch(index) { case GRPC_OP_SEND_INITIAL_METADATA: if (!create_metadata_array(value, &metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, "Bad metadata value given", 1); goto cleanup; } ops[op_num].data.send_initial_metadata.count = metadata.count; ops[op_num].data.send_initial_metadata.metadata = metadata.metadata; break; case GRPC_OP_SEND_MESSAGE: if (Z_TYPE_P(value) != IS_ARRAY) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected an array for send message", 1); goto cleanup; } message_hash = HASH_OF(value); if ((message_flags = zend_hash_str_find(message_hash, "flags", sizeof("flags") - 1)) != NULL) { if (Z_TYPE_P(message_flags) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected an int for message flags", 1); } ops[op_num].flags = Z_LVAL_P(message_flags) & GRPC_WRITE_USED_MASK; } if ((message_value = zend_hash_str_find( message_hash, "message", sizeof("message") - 1)) == NULL || Z_TYPE_P(message_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected a string for send message", 1); goto cleanup; } ops[op_num].data.send_message = string_to_byte_buffer(Z_STRVAL_P(message_value), Z_STRLEN_P(message_value)); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; case GRPC_OP_SEND_STATUS_FROM_SERVER: status_hash = HASH_OF(value); if ((inner_value = zend_hash_str_find( status_hash, "metadata", sizeof("metadata") - 1)) != NULL) { if (!create_metadata_array(inner_value, &trailing_metadata)) { zend_throw_exception(spl_ce_InvalidArgumentException, "Bad trailing metadata value given", 1); goto cleanup; } ops[op_num].data.send_status_from_server.trailing_metadata = trailing_metadata.metadata; ops[op_num].data.send_status_from_server.trailing_metadata_count = trailing_metadata.count; } if ((inner_value = zend_hash_str_find( status_hash, "code", sizeof("code") - 1)) != NULL) { if (Z_TYPE_P(inner_value) != IS_LONG) { zend_throw_exception(spl_ce_InvalidArgumentException, "Status code must be an integer", 1); goto cleanup; } ops[op_num].data.send_status_from_server.status = Z_LVAL_P(inner_value); } else { zend_throw_exception(spl_ce_InvalidArgumentException, "Integer status code is required", 1); goto cleanup; } if ((inner_value = zend_hash_str_find( status_hash, "details", sizeof("details") - 1)) != NULL) { if (Z_TYPE_P(inner_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Status details must be a string", 1); goto cleanup; } ops[op_num].data.send_status_from_server.status_details = Z_STRVAL_P(inner_value); } else { zend_throw_exception(spl_ce_InvalidArgumentException, "String status details is required", 1); goto cleanup; } break; case GRPC_OP_RECV_INITIAL_METADATA: ops[op_num].data.recv_initial_metadata = &recv_metadata; break; case GRPC_OP_RECV_MESSAGE: ops[op_num].data.recv_message = &message; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: ops[op_num].data.recv_status_on_client.trailing_metadata = &recv_trailing_metadata; ops[op_num].data.recv_status_on_client.status = &status; ops[op_num].data.recv_status_on_client.status_details = &status_details; ops[op_num].data.recv_status_on_client.status_details_capacity = &status_details_capacity; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: ops[op_num].data.recv_close_on_server.cancelled = &cancelled; break; default: zend_throw_exception(spl_ce_InvalidArgumentException, "Unrecognized key in batch", 1); goto cleanup; } ops[op_num].op = (grpc_op_type)index; ops[op_num].flags = 0; ops[op_num].reserved = NULL; op_num++; } //ZEND_HASH_FOREACH_END(); error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped, NULL); if (error != GRPC_CALL_OK) { zend_throw_exception(spl_ce_LogicException, "start_batch was called incorrectly", (long)error); goto cleanup; } grpc_completion_queue_pluck(completion_queue, call->wrapped, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); for (int i = 0; i < op_num; i++) { switch(ops[i].op) { case GRPC_OP_SEND_INITIAL_METADATA: add_property_bool(return_value, "send_metadata", true); break; case GRPC_OP_SEND_MESSAGE: add_property_bool(return_value, "send_message", true); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: add_property_bool(return_value, "send_close", true); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: add_property_bool(return_value, "send_status", true); break; case GRPC_OP_RECV_INITIAL_METADATA: grpc_parse_metadata_array(&recv_metadata, array); add_property_zval(return_value, "metadata", array); //Z_DELREF_P(array); break; case GRPC_OP_RECV_MESSAGE: byte_buffer_to_string(message, &message_str, &message_len); if (message_str == NULL) { add_property_null(return_value, "message"); } else { add_property_stringl(return_value, "message", message_str, message_len); } break; case GRPC_OP_RECV_STATUS_ON_CLIENT: object_init(&recv_status); grpc_parse_metadata_array(&recv_trailing_metadata, array); add_property_zval(&recv_status, "metadata", array); //Z_DELREF_P(array); add_property_long(&recv_status, "code", status); add_property_string(&recv_status, "details", status_details); add_property_zval(return_value, "status", &recv_status); //Z_DELREF_P(&recv_status); break; case GRPC_OP_RECV_CLOSE_ON_SERVER: add_property_bool(return_value, "cancelled", cancelled); break; default: break; } } cleanup: grpc_metadata_array_destroy(&metadata); grpc_metadata_array_destroy(&trailing_metadata); grpc_metadata_array_destroy(&recv_metadata); grpc_metadata_array_destroy(&recv_trailing_metadata); if (status_details != NULL) { gpr_free(status_details); } for (int i = 0; i < op_num; i++) { if (ops[i].op == GRPC_OP_SEND_MESSAGE) { grpc_byte_buffer_destroy(ops[i].data.send_message); } if (ops[i].op == GRPC_OP_RECV_MESSAGE) { grpc_byte_buffer_destroy(message); } } RETURN_DESTROY_ZVAL(return_value); }