├── .gitmodules ├── install.php ├── tests ├── tensile_construct_graph.phpt ├── tensile_construct_options.phpt ├── TF_OperationDescription___construct.phpt ├── tensile_options_target.phpt ├── TF_OperationDescription_setDevice.phpt ├── tensile_check_TF_version.phpt ├── tensile_construct_buffer.phpt ├── TF_Tensor_getDtype.phpt ├── tensile_status_setcode.phpt ├── TF_OperationDescription_setAttrInt.phpt ├── TF_OperationDescription_setAttrIntList.phpt ├── tensile_construct_tensor.phpt ├── TF_OperationDescription_setAttrFloat.phpt ├── TF_OperationDescription_setAttrFloatList.phpt ├── ex_Add.phpt ├── TF_OperationDescription_setAttrBool.phpt ├── TF_OperationDescription_setAttrType.phpt ├── TF_OperationDescription_setAttrTypeList.phpt ├── TF_OperationDescription_setAttrBoolList.phpt ├── tensile_Dtype_CONSTANTS.phpt └── tensile_status_constants.phpt ├── src ├── class │ ├── tf_dtype.h │ ├── tf_import_graph_def_options.h │ ├── tf_tensor.h │ ├── _sample.h │ ├── tf_graph.h │ ├── tf_input.h │ ├── tf_status.h │ ├── tf_output.h │ ├── tf_session.h │ ├── tf_session_options.h │ ├── tf_dtype.c │ ├── tf_operation_description.h │ ├── tf_buffer.h │ ├── tf_library.h │ ├── _sample.c │ ├── tf_graph.c │ ├── tf_input.c │ ├── tf_attr_metadata.h │ ├── tf_session_options.c │ ├── tf_buffer.c │ ├── tf_tensor.c │ ├── tf_status.c │ ├── tf_session.c │ ├── tf_operation.h │ └── tf_operation_description.c ├── utilities.c ├── php_tensile.h ├── utilities.h └── tensile.c ├── version.sh ├── .travis-docker.yml ├── config.m4 ├── .gitignore ├── LICENCE ├── Dockerfile ├── README.md ├── .travis.yml └── stubs └── tensile.php /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /install.php: -------------------------------------------------------------------------------- 1 | 8 | --EXPECT-- 9 | -------------------------------------------------------------------------------- /tests/tensile_construct_options.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\SessionOptions::__construct method 3 | --FILE-- 4 | 8 | --EXPECT-- 9 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription___construct.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::__construct method 3 | --FILE-- 4 | 7 | --EXPECT-- 8 | -------------------------------------------------------------------------------- /tests/tensile_options_target.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\SessionOptions::setTarget method 3 | --FILE-- 4 | setTarget("local"); 7 | 8 | ?> 9 | --EXPECT-- 10 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setDevice.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setDevice method 3 | --FILE-- 4 | setDevice("device"); 7 | 8 | ?> 9 | --EXPECT-- 10 | -------------------------------------------------------------------------------- /tests/tensile_check_TF_version.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | check bundled Tensorflow version 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 11 | --EXPECT-- 12 | 0 13 | -------------------------------------------------------------------------------- /src/class/tf_dtype.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_DTYPE_H 2 | #define PHP_TENSILE_DTYPE_H 3 | 4 | #include <../include/tensorflow/c/c_api.h>// use this only 5 | 6 | size_t tf_dtype_sizeof(TF_DataType type); 7 | 8 | char valid_dtype(int64_t dtype); 9 | 10 | #endif /* PHP_TENSILE_DTYPE_H */ 11 | -------------------------------------------------------------------------------- /version.sh: -------------------------------------------------------------------------------- 1 | # Tensorflow versions 2 | TF_TYPE=cpu 3 | TF_VERSION=1.12.0 4 | # Prep for build sequence 5 | sudo echo 'Getting latest Tensorflow build' 6 | sudo wget -qO - https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-${TF_TYPE}-linux-x86_64-${TF_VERSION}.tar.gz | tar zxf - -C . 7 | sudo echo 'Preparing for Tensile compilation' -------------------------------------------------------------------------------- /tests/tensile_construct_buffer.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\Buffer::__construct method 3 | --FILE-- 4 | __toString() ?: "(null)"), "\n"; 7 | $buffer = new Tensile\Buffer("hello tf!!"); 8 | echo ($buffer->__toString() ?: "(null)"), "\n"; 9 | 10 | ?> 11 | --EXPECT-- 12 | (null) 13 | hello tf!! 14 | -------------------------------------------------------------------------------- /.travis-docker.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | compiler: 7 | - gcc 8 | 9 | group: edge 10 | 11 | before_install: 12 | - docker pull absalomedia/tensile 13 | - docker ps -a 14 | - docker info 15 | 16 | script: 17 | - docker build -t absalomedia/tensile . 18 | 19 | notifications: 20 | on_success: never 21 | on_failure: never 22 | 23 | os: 24 | - linux -------------------------------------------------------------------------------- /tests/TF_Tensor_getDtype.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\Tensor::getDtype method 3 | --FILE-- 4 | getDtype(), "\n"; 8 | } 9 | 10 | ?> 11 | --EXPECT-- 12 | 1 13 | 2 14 | 3 15 | 4 16 | 5 17 | 6 18 | 7 19 | 8 20 | 9 21 | 10 22 | 11 23 | 12 24 | 13 25 | 14 26 | 15 27 | 16 28 | 17 29 | 18 30 | 19 31 | 20 32 | -------------------------------------------------------------------------------- /tests/tensile_status_setcode.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\Status::setCode method 3 | --FILE-- 4 | setCode(10, "hello tf!"); 7 | echo $status->getCode(), "\n"; 8 | echo $status->getMessage(), "\n"; 9 | 10 | $status->setCode(20); 11 | echo $status->getCode(), "\n"; 12 | echo ($status->getMessage() ?: "null"), "\n"; 13 | ?> 14 | --EXPECT-- 15 | 10 16 | hello tf! 17 | 20 18 | null 19 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrInt.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrInt method 3 | --FILE-- 4 | setAttrInt("pass", 1); 7 | $desc->setAttrInt("pass", 2); 8 | $desc->setAttrInt("pass", 3); 9 | $desc->setAttrInt("pass", "1.1"); 10 | 11 | $desc->setAttrInt(new stdClass); 12 | 13 | ?> 14 | --EXPECTF-- 15 | Warning: Tensile\OperationDescription::setAttrInt() expects exactly 2 parameters, 1 given in %s on line %d 16 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrIntList.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrIntList method 3 | --FILE-- 4 | setAttrIntList("pass", []); 7 | $desc->setAttrIntList("pass", [1]); 8 | $desc->setAttrIntList("pass", [1, 2]); 9 | try { 10 | $desc->setAttrIntList("fail", ["string"]); 11 | } catch (InvalidArgumentException $e) { 12 | echo $e->getMessage(), "\n"; 13 | } 14 | 15 | ?> 16 | --EXPECT-- 17 | values must be array of integer 18 | -------------------------------------------------------------------------------- /tests/tensile_construct_tensor.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\Tensor::__construct method 3 | --FILE-- 4 | getMessage(), "/{$i}\n"; 10 | } 11 | } 12 | $tensor = new Tensile\Tensor(Tensile\DTYPE_UINT16, []); // empty array safe 13 | $tensor = new Tensile\Tensor(Tensile\DTYPE_UINT16, NULL); // null safe 14 | 15 | ?> 16 | --EXPECT-- 17 | dtype must be from 1 to 20/0 18 | dtype must be from 1 to 20/21 19 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrFloat.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrFloat method 3 | --FILE-- 4 | setAttrFloat("pass", 1.0); 7 | $desc->setAttrFloat("pass", 2.1); 8 | $desc->setAttrFloat("pass", 3.3); 9 | $desc->setAttrFloat("pass", "3.3"); // safe 10 | 11 | $desc->setAttrFloat("fail", "string"); 12 | 13 | ?> 14 | --EXPECTF-- 15 | Warning: Tensile\OperationDescription::setAttrFloat() expects parameter 2 to be float, string given in %s on line %d 16 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrFloatList.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrFloatList method 3 | --FILE-- 4 | setAttrFloatList("pass", []); 7 | $desc->setAttrFloatList("pass", [1.0]); 8 | $desc->setAttrFloatList("pass", [1.0, 1.1]); 9 | try { 10 | $desc->setAttrFloatList("fail", ["string"]); 11 | } catch (InvalidArgumentException $e) { 12 | echo $e->getMessage(), "\n"; 13 | } 14 | 15 | ?> 16 | --EXPECT-- 17 | values must be array of float 18 | -------------------------------------------------------------------------------- /tests/ex_Add.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Example Add 3 | --FILE-- 4 | setAttrTensor("value", $tensor, NULL); 10 | // $desc->setAttrType("dtype", Tensile\DTYPE_INT32); 11 | // return $desc->finishOperation(NULL); 12 | // } 13 | 14 | // $graph = new Tensile\Graph(); 15 | 16 | // scalarConst($graph, 20); 17 | 18 | ?> 19 | --EXPECT-- 20 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrBool.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrBool method 3 | --FILE-- 4 | setAttrBool("true", true); 7 | $desc->setAttrBool("false", false); 8 | $desc->setAttrBool("false", "sdfasdf"); 9 | $desc->setAttrBool("false", 1); 10 | $desc->setAttrBool("false", 2); 11 | 12 | $desc->setAttrBool("string", new stdClass); 13 | 14 | ?> 15 | --EXPECTF-- 16 | Warning: Tensile\OperationDescription::setAttrBool() expects parameter 2 to be boolean, object given in %s on line %d 17 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_ENABLE(tensile, [whether to enable tensile extension], 2 | [ --enable-tensile Enable Tensile extension], yes, yes) 3 | 4 | if test "$PHP_TENSILE" != "no"; then 5 | PHP_ADD_INCLUDE(include) 6 | PHP_ADD_LIBRARY_WITH_PATH(tensorflow, lib, LIBTENSORFLOW_SHARED_LIBADD) 7 | 8 | LDFLAGS="-ltensorflow -L"`pwd`"/lib/ -lstdc++" 9 | 10 | PHP_NEW_EXTENSION(tensile, src/tensile.c src/utilities.c src/class/tf_buffer.c src/class/tf_dtype.c src/class/tf_graph.c src/class/tf_input.c src/class/tf_operation_description.c src/class/tf_session.c src/class/tf_status.c src/class/tf_tensor.c, $ext_shared) 11 | fi 12 | -------------------------------------------------------------------------------- /src/utilities.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Tensile 3 | * PHP bindings to Tensorflow 4 | * 5 | * https://github.com/absalomedia/tensile 6 | * Copyright (c)2017 Lawrence Meckan 7 | * 8 | * 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | #include "utilities.h" 15 | 16 | /** 17 | * A C implementation of PHP's trim() 18 | */ 19 | char *trim(char *str) 20 | { 21 | char *end; 22 | 23 | while(isspace(*str)) str++; 24 | 25 | if(*str == 0) 26 | { 27 | return str; 28 | } 29 | 30 | end = str + strlen(str) - 1; 31 | while(end > str && isspace(*end)) end--; 32 | 33 | *(end+1) = 0; 34 | 35 | return str; 36 | } -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrType.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrType method 3 | --FILE-- 4 | setAttrType("pass", 1); 7 | $desc->setAttrType("pass", 20); 8 | try { 9 | $desc->setAttrType("fail", 0); 10 | } catch (InvalidArgumentException $e) { 11 | echo $e->getMessage(), "\n"; 12 | } 13 | try { 14 | $desc->setAttrType("fail", 21); 15 | } catch (InvalidArgumentException $e) { 16 | echo $e->getMessage(), "\n"; 17 | } 18 | 19 | ?> 20 | --EXPECT-- 21 | dtype must be from 1 to 20 22 | dtype must be from 1 to 20 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.swp 3 | *.lo 4 | *.la 5 | .deps 6 | .libs 7 | Makefile 8 | Makefile.fragments 9 | Makefile.global 10 | Makefile.objects 11 | acinclude.m4 12 | aclocal.m4 13 | autom4te.cache 14 | config.cache 15 | config.guess 16 | config.h 17 | config.h.in 18 | config.log 19 | config.nice 20 | config.status 21 | config.sub 22 | configure 23 | configure.* 24 | conftest 25 | conftest.c 26 | install-sh 27 | libtool 28 | ltmain.sh 29 | missing 30 | mkinstalldirs 31 | modules 32 | scan_makefile_in.awk 33 | *.dsw 34 | *.plg 35 | *.opt 36 | *.ncb 37 | *.gz 38 | run-tests.php 39 | test.php 40 | build/* 41 | lib/* 42 | include/* 43 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | This software is licensed under the Apache 2 license, quoted below. 2 | 3 | Copyright 2015 Google. 4 | Copyright 2017 Lawrence Meckan 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | use this file except in compliance with the License. You may obtain a copy of 8 | the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | License for the specific language governing permissions and limitations under 16 | the License -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrTypeList.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrTypeList method 3 | --FILE-- 4 | setAttrTypeList("pass", []); 7 | $desc->setAttrTypeList("pass", [1]); 8 | $desc->setAttrTypeList("pass", [1, 2]); 9 | try { 10 | $desc->setAttrTypeList("fail", ["string"]); 11 | } catch (InvalidArgumentException $e) { 12 | echo $e->getMessage(), "\n"; 13 | } 14 | try { 15 | $desc->setAttrTypeList("fail", [0, 21]); 16 | } catch (InvalidArgumentException $e) { 17 | echo $e->getMessage(), "\n"; 18 | } 19 | 20 | ?> 21 | --EXPECT-- 22 | dtypes must be array of integer 23 | each dtype must be from 1 to 20 24 | -------------------------------------------------------------------------------- /tests/TF_OperationDescription_setAttrBoolList.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\OperationDescription::setAttrBoolList method 3 | --FILE-- 4 | setAttrBoolList("pass", []); 7 | $desc->setAttrBoolList("pass", [true]); 8 | $desc->setAttrBoolList("pass", [false]); 9 | $desc->setAttrBoolList("pass", [false, true]); 10 | $desc->setAttrBoolList("pass", [true, false]); 11 | $desc->setAttrBoolList("pass", [true, true]); 12 | $desc->setAttrBoolList("pass", [false, false]); 13 | try { 14 | $desc->setAttrBoolList("fail", [false, false, 1]); 15 | } catch (InvalidArgumentException $e) { 16 | echo $e->getMessage(), "\n"; 17 | } 18 | 19 | ?> 20 | --EXPECT-- 21 | values must be array of bool 22 | -------------------------------------------------------------------------------- /src/class/tf_import_graph_def_options.h: -------------------------------------------------------------------------------- 1 | // // TF_ImportGraphDefOptions holds options that can be passed to 2 | // // TF_GraphImportGraphDef. 3 | // typedef struct TF_ImportGraphDefOptions TF_ImportGraphDefOptions; 4 | 5 | // extern TF_ImportGraphDefOptions* TF_NewImportGraphDefOptions(); 6 | // extern void TF_DeleteImportGraphDefOptions(TF_ImportGraphDefOptions* opts); 7 | 8 | // // Set the prefix to be prepended to the names of nodes in `graph_def` that will 9 | // // be imported into `graph`. 10 | // extern void TF_ImportGraphDefOptionsSetPrefix(TF_ImportGraphDefOptions* opts, 11 | // const char* prefix); 12 | 13 | // // Import the graph serialized in `graph_def` into `graph`. 14 | // extern void TF_GraphImportGraphDef(TF_Graph* graph, const TF_Buffer* graph_def, 15 | // const TF_ImportGraphDefOptions* options, 16 | // TF_Status* status); 17 | 18 | -------------------------------------------------------------------------------- /src/class/tf_tensor.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_TENSOR_H 2 | #define PHP_TENSILE_TENSOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include <../src/utilities.h> 14 | #include "tf_dtype.h" 15 | #include <../include/tensorflow/c/c_api.h>// use this only 16 | 17 | #define TF_TENSOR_P_ZO(zo) ((t_tf_tensor_object*)((char *)(zo) - XtOffsetOf(t_tf_tensor_object, std))) 18 | #define TF_TENSOR_P_ZV(zv) TF_TENSOR_P_ZO(Z_OBJ_P(zv)) 19 | 20 | typedef struct _t_tf_tensor { 21 | TF_Tensor* src; 22 | char* str; 23 | int ref; 24 | } t_tf_tensor; 25 | 26 | typedef struct _t_tf_tensor_object { 27 | zend_object std; 28 | t_tf_tensor* ptr; 29 | } t_tf_tensor_object; 30 | 31 | void define_tf_tensor_class(); 32 | 33 | #endif /* PHP_TENSILE_TENSOR_H */ 34 | -------------------------------------------------------------------------------- /src/class/_sample.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_GRAPH_H 2 | #define PHP_TENSILE_GRAPH_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #define TF_GRAPH_P_ZO(zo) (t_tf_graph_object*)((char *)(zo) - XtOffsetOf(t_tf_graph_object, std)) 16 | #define TF_GRAPH_P_ZV(zv) TF_GRAPH_P_ZO(Z_OBJ_P(zv)) 17 | 18 | extern zend_class_entry *ce_TF_Graph; 19 | extern zend_object_handlers oh_TF_Graph; 20 | 21 | typedef struct _t_tf_graph { 22 | TF_Graph* src; 23 | char* str; 24 | int ref; 25 | } t_tf_graph; 26 | 27 | typedef struct _t_tf_graph_object { 28 | zend_object std; 29 | t_tf_graph* ptr; 30 | } t_tf_graph_object; 31 | 32 | void define_tf_graph_class(); 33 | 34 | #endif /* PHP_TENSILE_GRAPH_H */ 35 | -------------------------------------------------------------------------------- /src/class/tf_graph.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_GRAPH_H 2 | #define PHP_TENSILE_GRAPH_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #define TF_GRAPH_P_ZO(zo) ((t_tf_graph_object*)((char *)(zo) - XtOffsetOf(t_tf_graph_object, std))) 16 | #define TF_GRAPH_P_ZV(zv) TF_GRAPH_P_ZO(Z_OBJ_P(zv)) 17 | 18 | extern zend_class_entry *ce_TF_Graph; 19 | extern zend_object_handlers oh_TF_Graph; 20 | 21 | typedef struct _t_tf_graph { 22 | TF_Graph* src; 23 | char* str; 24 | int ref; 25 | } t_tf_graph; 26 | 27 | typedef struct _t_tf_graph_object { 28 | zend_object std; 29 | t_tf_graph* ptr; 30 | } t_tf_graph_object; 31 | 32 | void define_tf_graph_class(); 33 | 34 | #endif /* PHP_TENSILE_GRAPH_H */ 35 | -------------------------------------------------------------------------------- /src/class/tf_input.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_INPUT_H 2 | #define PHP_TENSILE_INPUT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #define TF_INPUT_P_ZO(zo) ((t_tf_input_object*)((char *)(zo) - XtOffsetOf(t_tf_input_object, std))) 16 | #define TF_INPUT_P_ZV(zv) TF_INPUT_P_ZO(Z_OBJ_P(zv)) 17 | 18 | extern zend_class_entry *ce_TF_Input; 19 | extern zend_object_handlers oh_TF_Input; 20 | 21 | typedef struct _t_tf_input { 22 | TF_Input* src; 23 | char* str; 24 | int ref; 25 | } t_tf_input; 26 | 27 | typedef struct _t_tf_input_object { 28 | zend_object std; 29 | t_tf_input* ptr; 30 | } t_tf_input_object; 31 | 32 | void define_tf_input_class(); 33 | 34 | #endif /* PHP_TENSILE_INPUT_H */ 35 | -------------------------------------------------------------------------------- /tests/tensile_Dtype_CONSTANTS.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\Dtype::* Constants 3 | --FILE-- 4 | 27 | --EXPECT-- 28 | 1 29 | 2 30 | 3 31 | 4 32 | 5 33 | 6 34 | 7 35 | 8 36 | 8 37 | 9 38 | 10 39 | 11 40 | 12 41 | 13 42 | 14 43 | 15 44 | 16 45 | 17 46 | 18 47 | 19 48 | 20 49 | -------------------------------------------------------------------------------- /src/class/tf_status.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_STATUS_H 2 | #define PHP_TENSILE_STATUS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #define TF_STATUS_P_ZO(zo) ((t_tf_status_object*)((char *)(zo) - XtOffsetOf(t_tf_status_object, std))) 16 | #define TF_STATUS_P_ZV(zv) TF_STATUS_P_ZO(Z_OBJ_P(zv)) 17 | 18 | extern zend_class_entry *ce_TF_Status; 19 | extern zend_object_handlers oh_TF_Status; 20 | 21 | typedef struct _t_tf_status { 22 | TF_Status* src; 23 | char* str; 24 | int ref; 25 | } t_tf_status; 26 | 27 | typedef struct _t_tf_status_object { 28 | zend_object std; 29 | t_tf_status* ptr; 30 | } t_tf_status_object; 31 | 32 | void define_tf_status_class(); 33 | 34 | t_tf_status_object* tf_status_object_fetch(zend_object *obj); 35 | 36 | #endif /* PHP_TENSILE_STATUS_H */ 37 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM absalomedia/bazel 2 | MAINTAINER Lawrence Meckan 3 | 4 | # Set correct environment variables. 5 | ENV DOCKER_NAME rev_tensile 6 | ENV DEBIAN_FRONTEND noninteractive 7 | ENV HOME /root 8 | ENV DEFAULT_TIMEZONE Australia/Brisbane 9 | 10 | # Tensorflow shared object 11 | ENV TF_TYPE=cpu 12 | ENV TF_OS=linux 13 | 14 | # Enable ssh access 15 | RUN rm -f /etc/service/sshd/down 16 | 17 | # Regenerate SSH host keys. baseimage-docker does not contain any, so you 18 | # have to do that yourself. You may also comment out this instruction; the 19 | # init system will auto-generate one during boot. 20 | # RUN /etc/my_init.d/00_regen_ssh_host_keys.sh 21 | 22 | # !!! Enabling the insecure key permanently !!! REMOVE ME AT PRODUCTION 23 | # RUN /usr/sbin/enable_insecure_key 24 | 25 | # Use baseimage-docker's init system. 26 | CMD ["/sbin/my_init"] 27 | 28 | WORKDIR /usr/src 29 | 30 | RUN git clone https://github.com/absalomedia/tensile.git && \ 31 | cd tensile 32 | RUN ./configure 33 | RUN bazel build -c opt tensorflow:libtensorflow.so 34 | -------------------------------------------------------------------------------- /tests/tensile_status_constants.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Tensile\Status::CODE_* Constants 3 | --FILE-- 4 | 23 | --EXPECT-- 24 | 0 25 | 1 26 | 2 27 | 3 28 | 4 29 | 5 30 | 6 31 | 7 32 | 8 33 | 9 34 | 10 35 | 11 36 | 12 37 | 13 38 | 14 39 | 15 40 | 16 41 | -------------------------------------------------------------------------------- /src/class/tf_output.h: -------------------------------------------------------------------------------- 1 | // // Represents a specific output of an operation. 2 | // typedef struct TF_Output { 3 | // TF_Operation* oper; 4 | // int index; // The index of the output within oper. 5 | // } TF_Output; 6 | 7 | 8 | // // Get the number of current consumers of a specific output of an 9 | // // operation. Note that this number can change when new operations 10 | // // are added to the graph. 11 | // extern int TF_OperationOutputNumConsumers(TF_Output oper_out); 12 | 13 | // // Get list of all current consumers of a specific output of an 14 | // // operation. `consumers` must point to an array of length at least 15 | // // `max_consumers` (ideally set to 16 | // // TF_OperationOutputNumConsumers(oper_out)). Beware that a concurrent 17 | // // modification of the graph can increase the number of consumers of 18 | // // an operation. Returns the number of output consumers (should match 19 | // // TF_OperationOutputNumConsumers(oper_out)). 20 | // extern int TF_OperationOutputConsumers(TF_Output oper_out, TF_Input* consumers, 21 | // int max_consumers); 22 | 23 | -------------------------------------------------------------------------------- /src/class/tf_session.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_SESSION_H 2 | #define PHP_TENSILE_SESSION_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #include "tf_graph.h" 16 | #include "tf_status.h" 17 | #include "tf_session_options.h" 18 | 19 | 20 | #define TF_SESSION_P_ZO(zo) ((t_tf_session_object*)((char *)(zo) - XtOffsetOf(t_tf_session_object, std))) 21 | #define TF_SESSION_P_ZV(zv) TF_SESSION_P_ZO(Z_OBJ_P(zv)) 22 | 23 | extern zend_class_entry *ce_TF_Session; 24 | extern zend_object_handlers oh_TF_Session; 25 | 26 | typedef struct _t_tf_session { 27 | TF_Session* src; 28 | char* str; 29 | int ref; 30 | } t_tf_session; 31 | 32 | typedef struct _t_tf_session_object { 33 | zend_object std; 34 | t_tf_session* ptr; 35 | } t_tf_session_object; 36 | 37 | void define_tf_session_class(); 38 | 39 | #endif /* PHP_TENSILE_SESSION_H */ 40 | -------------------------------------------------------------------------------- /src/class/tf_session_options.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_SESSION_OPTIONS_H 2 | #define PHP_TENSILE_SESSION_OPTIONS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #define TF_SESSION_OPTIONS_P_ZO(zo) ((t_tf_session_options_object*)((char *)(zo) - XtOffsetOf(t_tf_session_options_object, std))) 16 | #define TF_SESSION_OPTIONS_P_ZV(zv) TF_SESSION_OPTIONS_P_ZO(Z_OBJ_P(zv)) 17 | 18 | extern zend_class_entry *ce_TF_SessionOptions; 19 | extern zend_object_handlers oh_TF_SessionOptions; 20 | 21 | typedef struct _t_tf_session_options { 22 | TF_SessionOptions* src; 23 | char* str; 24 | int ref; 25 | } t_tf_session_options; 26 | 27 | typedef struct _t_tf_session_options_object { 28 | zend_object std; 29 | t_tf_session_options* ptr; 30 | } t_tf_session_options_object; 31 | 32 | void define_tf_session_options_class(); 33 | 34 | #endif /* PHP_TENSILE_SESSION_OPTIONS_H */ 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tensile 2 | 3 | The `tensile` extension for PHP gives you an object-oriented system for utilising Google's Tensorflow Machine Learning (http://tensorflow.org) from within your PHP applications. Still not in fully working state & experimental builds. 4 | 5 | 6 | ![Tensorflow 1.12.0](https://img.shields.io/badge/tensorflow-1.12.0-blue.svg) [![Build Status](https://travis-ci.org/absalomedia/tensile.svg?branch=master)](https://travis-ci.org/absalomedia/tensile) [![Patreon](https://img.shields.io/badge/patreon-donate-green.svg)](https://www.patreon.com/bePatron?u=14641360) 7 | 8 | # Concept 9 | 10 | The concept of this extension is to expose Tensorflow into PHP directly so you can run rules, training & the Tensorflow engine natively via PHP code. The coding structure replicates my work having SASS compile on the fly as a PHP extension. 11 | 12 | # Steps 13 | - [x] Build a base test image to test this build process (Travis/Docker) 14 | - [x] Build a shared library off Tensorflow. 15 | - [ ] Refactor header classes from SASSPHP to deal with Tensorflow functions, variables & classes. 16 | - [ ] Refactor C/C++ code to allow PHP classes to talk directly / manage Tensorflow once it's wrapped in shared library 17 | - [ ] Build tests 18 | - [ ] Build PHP stub 19 | - [ ] Profit 20 | -------------------------------------------------------------------------------- /src/class/tf_dtype.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_dtype.h" 3 | 4 | /** 5 | * @ref https://github.com/tensorflow/tensorflow/blob/287db3a9b0701021f302e7bb58af5cf89fdcd424/tensorflow/java/src/main/native/tensor_jni.cc 6 | */ 7 | size_t tf_dtype_sizeof(TF_DataType type) 8 | { 9 | switch (type) { 10 | case TF_INT8 : 11 | case TF_UINT8 : 12 | case TF_QINT8 : 13 | case TF_QUINT8 : 14 | case TF_BOOL : 15 | return 1; 16 | case TF_INT16 : 17 | case TF_BFLOAT16 : 18 | case TF_QINT16 : 19 | case TF_QUINT16 : 20 | case TF_UINT16 : 21 | return 2; 22 | case TF_FLOAT : 23 | case TF_INT32 : 24 | case TF_QINT32 : 25 | return 4; 26 | case TF_DOUBLE : 27 | case TF_INT64 : 28 | case TF_COMPLEX64 : // equal TF_COMPLEX 29 | return 8; 30 | case TF_COMPLEX128 : 31 | return 16; 32 | default: 33 | break; 34 | // @todo 35 | // case TF_STRING : nbytes = uintptr(nflattened*8) + byteSizeOfEncodedStrings(value) 36 | // case TF_HALF : 37 | // case TF_RESOURCE : 38 | } 39 | return 0; // unknown; 40 | } 41 | 42 | char valid_dtype(int64_t dtype) 43 | { 44 | return dtype > 0 && dtype < 21; 45 | } 46 | -------------------------------------------------------------------------------- /src/class/tf_operation_description.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_OPERATION_DESCRIPTION_H 2 | #define PHP_TENSILE_OPERATION_DESCRIPTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include <../include/tensorflow/c/c_api.h>// use this only 14 | #include <../src/utilities.h> 15 | 16 | #include "tf_dtype.h" 17 | #include "tf_graph.h" 18 | 19 | #define TF_OPERATION_DESCRIPTION_P_ZO(zo) (t_tf_operation_description_object*)((char *)(zo) - XtOffsetOf(t_tf_operation_description_object, std)) 20 | #define TF_OPERATION_DESCRIPTION_P_ZV(zv) TF_OPERATION_DESCRIPTION_P_ZO(Z_OBJ_P(zv)) 21 | 22 | extern zend_class_entry *ce_TF_OperationDescription; 23 | extern zend_object_handlers oh_TF_OperationDescription; 24 | 25 | typedef struct _t_tf_operation_description { 26 | TF_OperationDescription* src; 27 | char* str; 28 | int ref; 29 | } t_tf_operation_description; 30 | 31 | typedef struct _t_tf_operation_description_object { 32 | zend_object std; 33 | t_tf_operation_description* ptr; 34 | } t_tf_operation_description_object; 35 | 36 | void define_tf_operation_description_class(); 37 | 38 | #endif /* PHP_TENSILE_OPERATION_DESCRIPTION_H */ 39 | -------------------------------------------------------------------------------- /src/class/tf_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TENSILE_BUFFER_H 2 | #define PHP_TENSILE_BUFFER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include <../include/tensorflow/c/c_api.h>// use this only 13 | #include <../src/utilities.h> 14 | 15 | #define TF_BUFFER_P_ZO(zo) ((t_tf_buffer_object*)((char *)(zo) - XtOffsetOf(t_tf_buffer_object, std))) 16 | #define TF_BUFFER_P_ZV(zv) TF_BUFFER_P_ZO(Z_OBJ_P(zv)) 17 | 18 | extern zend_class_entry *ce_TF_Buffer; 19 | extern zend_object_handlers oh_TF_Buffer; 20 | 21 | typedef struct _t_tf_buffer { 22 | TF_Buffer* src; 23 | char* str; 24 | int ref; 25 | } t_tf_buffer; 26 | 27 | typedef struct _t_tf_buffer_object { 28 | zend_object std; 29 | t_tf_buffer* ptr; 30 | } t_tf_buffer_object; 31 | 32 | void define_tf_buffer_class(); 33 | 34 | #endif /* PHP_TENSILE_BUFFER_H */ 35 | 36 | 37 | 38 | // // Get the OpList of all OpDefs defined in this address space. 39 | // // Returns a TF_Buffer, ownership of which is transferred to the caller 40 | // // (and can be freed using TF_DeleteBuffer). 41 | // // 42 | // // The data in the buffer will be the serialized OpList proto for ops registered 43 | // // in this address space. 44 | // extern TF_Buffer* TF_GetAllOpList(); 45 | 46 | -------------------------------------------------------------------------------- /src/class/tf_library.h: -------------------------------------------------------------------------------- 1 | // // TF_Library holds information about dynamically loaded TensorFlow plugins. 2 | // typedef struct TF_Library TF_Library; 3 | 4 | // // Load the library specified by library_filename and register the ops and 5 | // // kernels present in that library. 6 | // // 7 | // // Pass "library_filename" to a platform-specific mechanism for dynamically 8 | // // loading a library. The rules for determining the exact location of the 9 | // // library are platform-specific and are not documented here. 10 | // // 11 | // // On success, place OK in status and return the newly created library handle. 12 | // // The caller owns the library handle. 13 | // // 14 | // // On failure, place an error status in status and return NULL. 15 | // extern TF_Library* TF_LoadLibrary(const char* library_filename, 16 | // TF_Status* status); 17 | 18 | // // Get the OpList of OpDefs defined in the library pointed by lib_handle. 19 | // // 20 | // // Returns a TF_Buffer. The memory pointed to by the result is owned by 21 | // // lib_handle. The data in the buffer will be the serialized OpList proto for 22 | // // ops defined in the library. 23 | // extern TF_Buffer TF_GetOpList(TF_Library* lib_handle); 24 | 25 | // // Frees the memory associated with the library handle. 26 | // // Does NOT unload the library. 27 | // extern void TF_DeleteLibraryHandle(TF_Library* lib_handle); 28 | -------------------------------------------------------------------------------- /src/class/_sample.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_graph.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Graph = NULL; 6 | zend_object_handlers oh_TF_Graph; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_Graph, __construct); 10 | static PHP_METHOD(TensorFlow_Graph, __destruct); 11 | 12 | // argument info 13 | // ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_graph_setCode, 0, 0, 1) 14 | // ZEND_ARG_INFO(0, code) 15 | // ZEND_ARG_INFO(0, message) 16 | // ZEND_END_ARG_INFO() 17 | 18 | // methods 19 | static zend_function_entry tf_graph_methods[] = { 20 | PHP_ME(TensorFlow_Graph, __construct, NULL, ZEND_ACC_PUBLIC) 21 | PHP_ME(TensorFlow_Graph, __destruct, NULL, ZEND_ACC_PUBLIC) 22 | PHP_FE_END 23 | }; 24 | 25 | CA_OBJECT_CREATE(graph, t_tf_graph, t_tf_graph_object, oh_TF_Graph) 26 | CA_OBJECT_FREE(graph, t_tf_graph, t_tf_graph_object) 27 | 28 | void define_tf_graph_class() 29 | { 30 | DEFINE_CLASS(Graph, graph, ce_TF_Graph, oh_TF_Graph) 31 | } 32 | 33 | // extern TF_Graph* TF_NewGraph(); 34 | static PHP_METHOD(TensorFlow_Graph, __construct) 35 | { 36 | t_tf_graph_object* intern = TF_GRAPH_P_ZV(getThis()); 37 | t_tf_graph* node = intern->ptr; 38 | 39 | node->src = TF_NewGraph(); 40 | } 41 | 42 | // extern void TF_DeleteGraph(TF_Graph*); 43 | static PHP_METHOD(TensorFlow_Graph, __destruct) 44 | { 45 | t_tf_graph_object* intern = TF_GRAPH_P_ZV(getThis()); 46 | t_tf_graph* node = intern->ptr; 47 | 48 | TF_DeleteGraph(node->src); 49 | } 50 | -------------------------------------------------------------------------------- /src/class/tf_graph.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_graph.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Graph = NULL; 6 | zend_object_handlers oh_TF_Graph; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_Graph, __construct); 10 | static PHP_METHOD(TensorFlow_Graph, __destruct); 11 | 12 | // argument info 13 | // ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_graph_setCode, 0, 0, 1) 14 | // ZEND_ARG_INFO(0, code) 15 | // ZEND_ARG_INFO(0, message) 16 | // ZEND_END_ARG_INFO() 17 | 18 | // methods 19 | static zend_function_entry tf_graph_methods[] = { 20 | PHP_ME(TensorFlow_Graph, __construct, NULL, ZEND_ACC_PUBLIC) 21 | PHP_ME(TensorFlow_Graph, __destruct, NULL, ZEND_ACC_PUBLIC) 22 | PHP_FE_END 23 | }; 24 | 25 | CA_OBJECT_CREATE(graph, t_tf_graph, t_tf_graph_object, oh_TF_Graph) 26 | CA_OBJECT_FREE(graph, t_tf_graph, t_tf_graph_object) 27 | 28 | void define_tf_graph_class() 29 | { 30 | DEFINE_CLASS(Graph, graph, ce_TF_Graph, oh_TF_Graph) 31 | } 32 | 33 | // extern TF_Graph* TF_NewGraph(); 34 | static PHP_METHOD(TensorFlow_Graph, __construct) 35 | { 36 | t_tf_graph_object* intern = TF_GRAPH_P_ZV(getThis()); 37 | t_tf_graph* node = intern->ptr; 38 | 39 | node->src = TF_NewGraph(); 40 | } 41 | 42 | // extern void TF_DeleteGraph(TF_Graph*); 43 | static PHP_METHOD(TensorFlow_Graph, __destruct) 44 | { 45 | t_tf_graph_object* intern = TF_GRAPH_P_ZV(getThis()); 46 | t_tf_graph* node = intern->ptr; 47 | 48 | TF_DeleteGraph(node->src); 49 | } 50 | -------------------------------------------------------------------------------- /src/php_tensile.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Tensile 3 | * PHP bindings to Tensorflow 4 | * 5 | * https://github.com/absalomedia/tensile 6 | * Copyright (c) 2017-2019 Lawrence Meckan 7 | * 8 | * 9 | */ 10 | 11 | 12 | #ifndef PHP_TENSILE_H 13 | #define PHP_TENSILE_H 14 | 15 | #ifdef HAVE_CONFIG_H 16 | #include "config.h" 17 | #endif 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include "utilities.h" 30 | 31 | zend_class_entry *tensile_ce; 32 | zend_class_entry *tensile_exception_ce; 33 | 34 | zend_class_entry *tensile_get_exception_base(); 35 | 36 | #define TENSILE_VERSION "0.9.0" 37 | #define TENSILE_FLAVOR "Tonewood" 38 | 39 | #define TENSILE_NS "Tensile" 40 | 41 | #define TF_BUFFER_P_ZO(zo) ((t_tf_buffer_object*)((char *)(zo) - XtOffsetOf(t_tf_buffer_object, std))) 42 | #define TF_BUFFER_P_ZV(zv) TF_BUFFER_P_ZO(Z_OBJ_P(zv)) 43 | 44 | extern zend_class_entry *ce_TF_Buffer; 45 | extern zend_object_handlers oh_TF_Buffer; 46 | 47 | typedef struct _t_tf_buffer { 48 | TF_Buffer* src; 49 | char* str; 50 | int ref; 51 | } t_tf_buffer; 52 | 53 | typedef struct _t_tf_buffer_object { 54 | zend_object std; 55 | t_tf_buffer* ptr; 56 | } t_tf_buffer_object; 57 | 58 | void define_tf_buffer_class(); 59 | 60 | size_t tf_dtype_sizeof(TF_DataType type); 61 | 62 | char valid_dtype(int64_t dtype); 63 | 64 | 65 | static PHP_MINFO_FUNCTION(tensile); 66 | static PHP_MINIT_FUNCTION(tensile); 67 | 68 | extern zend_module_entry tensile_module_entry; 69 | 70 | #endif -------------------------------------------------------------------------------- /src/class/tf_input.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_input.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Input = NULL; 6 | zend_object_handlers oh_TF_Input; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_Input, __construct); 10 | static PHP_METHOD(TensorFlow_Input, __destruct); 11 | 12 | // argument info 13 | // ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_input_setCode, 0, 0, 1) 14 | // ZEND_ARG_INFO(0, code) 15 | // ZEND_ARG_INFO(0, message) 16 | // ZEND_END_ARG_INFO() 17 | 18 | // methods 19 | static zend_function_entry tf_input_methods[] = { 20 | PHP_ME(TensorFlow_Input, __construct, NULL, ZEND_ACC_PUBLIC) 21 | PHP_ME(TensorFlow_Input, __destruct, NULL, ZEND_ACC_PUBLIC) 22 | PHP_FE_END 23 | }; 24 | 25 | CA_OBJECT_CREATE(input, t_tf_input, t_tf_input_object, oh_TF_Input) 26 | CA_OBJECT_FREE(input, t_tf_input, t_tf_input_object) 27 | 28 | void define_tf_input_class() 29 | { 30 | DEFINE_CLASS(Input, input, ce_TF_Input, oh_TF_Input) 31 | } 32 | 33 | // // Represents a specific input of an operation. 34 | // typedef struct TF_Input { 35 | // TF_Operation* oper; 36 | // int index; // The index of the input within oper. 37 | // } TF_Input; 38 | 39 | static PHP_METHOD(TensorFlow_Input, __construct) 40 | { 41 | t_tf_input_object* intern = TF_INPUT_P_ZV(getThis()); 42 | t_tf_input* node = intern->ptr; 43 | 44 | node->src = (TF_Input*)emalloc(sizeof(TF_Input)); 45 | node->src->oper = NULL; // OPER; 46 | node->src->index = 0; 47 | } 48 | 49 | // // In this code: 50 | // // TF_Output producer = TF_OperationInput(consumer); 51 | // // There is an edge from producer.oper's output (given by 52 | // // producer.index) to consumer.oper's input (given by consumer.index). 53 | // extern TF_Output TF_OperationInput(TF_Input oper_in); 54 | static PHP_METHOD(TensorFlow_Input, __destruct) 55 | { 56 | t_tf_input_object* intern = TF_INPUT_P_ZV(getThis()); 57 | t_tf_input* node = intern->ptr; 58 | 59 | node->src; // ? 60 | } 61 | -------------------------------------------------------------------------------- /src/class/tf_attr_metadata.h: -------------------------------------------------------------------------------- 1 | // // TF_AttrType describes the type of the value of an attribute on an operation. 2 | // typedef enum { 3 | // TF_ATTR_STRING = 0, 4 | // TF_ATTR_INT = 1, 5 | // TF_ATTR_FLOAT = 2, 6 | // TF_ATTR_BOOL = 3, 7 | // TF_ATTR_TYPE = 4, 8 | // TF_ATTR_SHAPE = 5, 9 | // TF_ATTR_TENSOR = 6, 10 | // TF_ATTR_PLACEHOLDER = 7, 11 | // TF_ATTR_FUNC = 8, 12 | // } TF_AttrType; 13 | 14 | 15 | // // TF_AttrMetadata describes the value of an attribute on an operation. 16 | // typedef struct { 17 | // // A boolean: 1 if the attribute value is a list, 0 otherwise. 18 | // unsigned char is_list; 19 | 20 | // // Length of the list if is_list is true. Undefined otherwise. 21 | // int64_t list_size; 22 | 23 | // // Type of elements of the list if is_list != 0. 24 | // // Type of the single value stored in the attribute if is_list == 0. 25 | // TF_AttrType type; 26 | 27 | // // Total size the attribute value. 28 | // // The units of total_size depend on is_list and type. 29 | // // (1) If type == TF_ATTR_STRING and is_list == 0 30 | // // then total_size is the byte size of the string 31 | // // valued attribute. 32 | // // (2) If type == TF_ATTR_STRING and is_list == 1 33 | // // then total_size is the cumulative byte size 34 | // // of all the strings in the list. 35 | // // (3) If type == TF_ATTR_SHAPE and is_list == 0 36 | // // then total_size is the number of dimensions 37 | // // of the shape valued attribute, or -1 38 | // // if its rank is unknown. 39 | // // (4) If type == TF_ATTR_SHAPE and is_list == 1 40 | // // then total_size is the cumulative number 41 | // // of dimensions of all shapes in the list. 42 | // // (5) Otherwise, total_size is undefined. 43 | // int64_t total_size; 44 | // } TF_AttrMetadata; 45 | 46 | // // Returns metadata about the value of the attribute `attr_name` of `oper`. 47 | // extern TF_AttrMetadata TF_OperationGetAttrMetadata(TF_Operation* oper, 48 | // const char* attr_name, 49 | // TF_Status* status); 50 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.5 4 | - 5.6 5 | - 7.0 6 | - 7.1 7 | - 7.2 8 | - nightly 9 | 10 | allow_failures: 11 | - php: nightly 12 | 13 | addons: 14 | apt: 15 | packages: 16 | - php5-dev 17 | - gdb 18 | 19 | env: 20 | global: 21 | # Configure the .phpt tests to be Travis friendly 22 | - REPORT_EXIT_STATUS=1 23 | - TEST_PHP_ARGS="-q -s output.txt -g XFAIL,FAIL,BORK,WARN,LEAK,SKIP -x --show-diff" 24 | # Add the pip installation folder to the PATH, until https://github.com/travis-ci/travis-ci/issues/3563 is fixed 25 | - PATH=$HOME/.local/bin:$PATH 26 | 27 | compiler: 28 | - gcc 29 | 30 | install: 31 | # What is the current file size max for core files? 32 | # It is usually 0, which means no core file will be dumped if there is a crash 33 | - ulimit -c 34 | 35 | before_install: 36 | - echo $LANG 37 | - echo $LC_ALL 38 | - composer require satooshi/php-coveralls --dev 39 | 40 | before_script: 41 | - travis_retry composer self-update 42 | - composer config discard-changes true 43 | - ulimit -c unlimited -S # enable core dumps 44 | 45 | script: 46 | - ./version.sh 47 | - make clean 48 | - phpize 49 | - ./configure 50 | - make 51 | - echo "extension = tensile.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini 52 | - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${TRAVIS_BUILD_DIR}/modules" 53 | - make install 54 | - mkdir -p build/logs 55 | - phpunit --coverage-clover build/logs/clover.xml 56 | - make test || RESULT=$? 57 | - if [[ ${RESULT} == 0 ]]; then echo "\\o/ our test worked without problems"; else echo "ruhroh test returned an errorcode of $RESULT"; fi; 58 | - for i in $(find ./ -maxdepth 1 -name 'core*' -print); do gdb $(pwd)/test core* -ex "thread apply all bt" -ex "set pagination 0" -batch; done; 59 | - if [[ ${RESULT} != 0 ]]; then exit $RESULT ; fi; 60 | 61 | after_success: 62 | - travis_retry php vendor/bin/coveralls 63 | 64 | notifications: 65 | on_success: never 66 | on_failure: never 67 | 68 | 69 | os: 70 | - linux 71 | 72 | matrix: 73 | fast_finish: true 74 | -------------------------------------------------------------------------------- /src/utilities.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Tensile 3 | * PHP bindings to Tensorflow 4 | * 5 | * https://github.com/absalomedia/tensile 6 | * Copyright (c) 2017-2019 Lawrence Meckan 7 | * 8 | * 9 | */ 10 | 11 | #ifndef UTILITIES_H 12 | #define UTILITIES_H 13 | 14 | char *trim(char *str); 15 | 16 | #define DEFINE_CLASS(Name, name, class_entry, object_handler) \ 17 | zend_class_entry temp_ce; \ 18 | INIT_NS_CLASS_ENTRY(temp_ce, "Tensile", #Name, tf_##name##_methods); \ 19 | class_entry = zend_register_internal_class(&temp_ce); \ 20 | class_entry->create_object = tf_##name##_object_create; \ 21 | memcpy(&object_handler, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \ 22 | object_handler.clone_obj = NULL; \ 23 | object_handler.free_obj = tf_##name##_object_free; \ 24 | object_handler.offset = XtOffsetOf(t_tf_##name##_object, std); 25 | 26 | #define CA_OBJECT_CREATE(name, t_class, t_class_object, object_handler) \ 27 | zend_object* tf_##name##_object_create(zend_class_entry *ce TSRMLS_DC) { \ 28 | t_class_object* intern; \ 29 | t_class *node = NULL; \ 30 | intern = (t_class_object *)ecalloc(1, sizeof(t_class_object)); \ 31 | node = (t_class *)ecalloc(1, sizeof(t_class)); \ 32 | if (node != NULL) { \ 33 | node->src = NULL; \ 34 | node->str = NULL; \ 35 | node->ref = 1; \ 36 | } \ 37 | intern->ptr = node; \ 38 | zend_object_std_init(&intern->std, ce TSRMLS_CC); \ 39 | object_properties_init(&intern->std, ce); \ 40 | intern->std.handlers = &object_handler; \ 41 | return &intern->std; \ 42 | } 43 | 44 | #define CA_OBJECT_FREE(name, t_class, t_class_object) \ 45 | static void tf_##name##_object_free(zend_object *object TSRMLS_DC) { \ 46 | t_class_object* intern = (t_class_object*)((char *)object - XtOffsetOf(t_class_object, std)); \ 47 | t_class* node = intern->ptr; \ 48 | node->ref--; \ 49 | if (node->ref == 0) { \ 50 | if (node->str != NULL) { \ 51 | zend_string_release(node->str); \ 52 | } \ 53 | efree(node); \ 54 | } \ 55 | zend_object_std_dtor(&intern->std TSRMLS_CC); \ 56 | } 57 | 58 | #endif /* UTILITIES_H */ -------------------------------------------------------------------------------- /src/class/tf_session_options.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_session_options.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_SessionOptions = NULL; 6 | zend_object_handlers oh_TF_SessionOptions; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_SessionOptions, __construct); 10 | static PHP_METHOD(TensorFlow_SessionOptions, __destruct); 11 | static PHP_METHOD(TensorFlow_SessionOptions, setTarget); 12 | 13 | // argument info 14 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_session_options_setTarget, 0, 0, 1) 15 | ZEND_ARG_INFO(0, target) 16 | ZEND_END_ARG_INFO() 17 | 18 | // methods 19 | static zend_function_entry tf_session_options_methods[] = { 20 | PHP_ME(TensorFlow_SessionOptions, __construct, NULL, ZEND_ACC_PUBLIC) 21 | PHP_ME(TensorFlow_SessionOptions, __destruct, NULL, ZEND_ACC_PUBLIC) 22 | PHP_ME(TensorFlow_SessionOptions, setTarget, arginfo_tf_session_options_setTarget, ZEND_ACC_PUBLIC) 23 | PHP_FE_END 24 | }; 25 | 26 | CA_OBJECT_CREATE(session_options, t_tf_session_options, t_tf_session_options_object, oh_TF_SessionOptions) 27 | CA_OBJECT_FREE(session_options, t_tf_session_options, t_tf_session_options_object) 28 | 29 | void define_tf_session_options_class() 30 | { 31 | DEFINE_CLASS(SessionOptions, session_options, ce_TF_SessionOptions, oh_TF_SessionOptions) 32 | } 33 | 34 | // extern TF_SessionOptions* TF_NewSessionOptions(); 35 | static PHP_METHOD(TensorFlow_SessionOptions, __construct) 36 | { 37 | t_tf_session_options_object* intern = TF_SESSION_OPTIONS_P_ZV(getThis()); 38 | t_tf_session_options* node = intern->ptr; 39 | 40 | node->src = TF_NewSessionOptions(); 41 | } 42 | 43 | // extern void TF_DeleteSessionOptions(TF_SessionOptions*); 44 | static PHP_METHOD(TensorFlow_SessionOptions, __destruct) 45 | { 46 | t_tf_session_options_object* intern = TF_SESSION_OPTIONS_P_ZV(getThis()); 47 | t_tf_session_options* node = intern->ptr; 48 | 49 | TF_DeleteSessionOptions(node->src); 50 | } 51 | 52 | // extern void TF_SetTarget(TF_SessionOptions* options, const char* target); 53 | static PHP_METHOD(TensorFlow_SessionOptions, setTarget) 54 | { 55 | zend_string *target; 56 | 57 | ZEND_PARSE_PARAMETERS_START(1, 1) 58 | Z_PARAM_STR(target) 59 | ZEND_PARSE_PARAMETERS_END(); 60 | 61 | // php_printf("target : %s\n", target->val); 62 | 63 | t_tf_session_options_object* intern = TF_SESSION_OPTIONS_P_ZV(getThis()); 64 | t_tf_session_options* node = intern->ptr; 65 | 66 | TF_SetTarget(node->src, target->val); 67 | } 68 | -------------------------------------------------------------------------------- /src/class/tf_buffer.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_buffer.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Buffer = NULL; 6 | zend_object_handlers oh_TF_Buffer; 7 | 8 | // methods 9 | static PHP_METHOD(Tensile_Buffer, __construct); 10 | static PHP_METHOD(Tensile_Buffer, __destruct); 11 | static PHP_METHOD(Tensile_Buffer, __toString); 12 | 13 | // argument info 14 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_buffer___construct, 0, 0, 0) 15 | ZEND_ARG_INFO(0, buffer) 16 | ZEND_END_ARG_INFO() 17 | 18 | // methods 19 | static zend_function_entry tf_buffer_methods[] = { 20 | PHP_ME(Tensile_Buffer, __construct, arginfo_tf_buffer___construct, ZEND_ACC_PUBLIC) 21 | PHP_ME(Tensile_Buffer, __destruct, NULL, ZEND_ACC_PUBLIC) 22 | PHP_ME(Tensile_Buffer, __toString, NULL, ZEND_ACC_PUBLIC) 23 | PHP_FE_END 24 | }; 25 | 26 | CA_OBJECT_CREATE(buffer, t_tf_buffer, t_tf_buffer_object, oh_TF_Buffer) 27 | CA_OBJECT_FREE(buffer, t_tf_buffer, t_tf_buffer_object) 28 | 29 | void define_tf_buffer_class() 30 | { 31 | DEFINE_CLASS(Buffer, buffer, ce_TF_Buffer, oh_TF_Buffer) 32 | } 33 | 34 | // extern TF_Buffer* TF_NewBufferFromString(const void* proto, size_t proto_len); 35 | // extern TF_Buffer* TF_NewBuffer(); 36 | static PHP_METHOD(Tensile_Buffer, __construct) 37 | { 38 | // arguments 39 | char* buffer; 40 | 41 | ZEND_PARSE_PARAMETERS_START(0, 1) 42 | Z_PARAM_OPTIONAL 43 | Z_PARAM_STR(buffer) 44 | ZEND_PARSE_PARAMETERS_END(); 45 | 46 | // this 47 | t_tf_buffer_object* intern; 48 | t_tf_buffer* php_tf_buffer; 49 | 50 | intern = TF_BUFFER_P_ZV(getThis()); 51 | php_tf_buffer = intern->ptr; 52 | 53 | if (ZEND_NUM_ARGS() == 1) { 54 | php_tf_buffer->src = TF_NewBufferFromString(ZSTR_VAL(buffer), ZSTR_LEN(buffer)); 55 | } else { 56 | php_tf_buffer->src = TF_NewBuffer(); 57 | } 58 | } 59 | 60 | // extern void TF_DeleteBuffer(TF_Buffer*); 61 | static PHP_METHOD(Tensile_Buffer, __destruct) 62 | { 63 | // this 64 | t_tf_buffer_object* intern; 65 | t_tf_buffer* node; 66 | 67 | intern = TF_BUFFER_P_ZV(getThis()); 68 | node = intern->ptr; 69 | 70 | TF_DeleteBuffer(node->src); 71 | } 72 | 73 | // extern TF_Buffer TF_GetBuffer(TF_Buffer* buffer); 74 | static PHP_METHOD(Tensile_Buffer, __toString) 75 | { 76 | char* result; 77 | 78 | // this 79 | t_tf_buffer_object* intern; 80 | t_tf_buffer* node; 81 | TF_Buffer* tf_buffer; 82 | 83 | intern = TF_BUFFER_P_ZV(getThis()); 84 | node = intern->ptr; 85 | tf_buffer = node->src; 86 | 87 | 88 | RETURN_STR(zend_string_init(tf_buffer->data, tf_buffer->length, 0)); 89 | } 90 | -------------------------------------------------------------------------------- /src/tensile.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Tensile 3 | * PHP bindings to Tensorflow 4 | * 5 | * https://github.com/absalomedia/tensile 6 | * Copyright (c)2017 Lawrence Meckan 7 | * 8 | */ 9 | 10 | #include 11 | #if ZEND_MODULE_API_NO > 20131226 12 | #include 13 | #endif 14 | 15 | #include "php_tensile.h" 16 | #include "utilities.h" 17 | 18 | // functions 19 | static zend_function_entry tf_functions[] = { 20 | {NULL, NULL, NULL} 21 | }; 22 | 23 | // the following code creates an entry for the module and registers it with Zend. 24 | zend_module_entry tensile_module_entry = { 25 | #if ZEND_MODULE_API_NO >= 20010901 26 | STANDARD_MODULE_HEADER, 27 | #endif 28 | TENSILE_FLAVOR, 29 | tf_functions, 30 | PHP_MINIT(tensile), 31 | NULL, // name of the MSHUTDOWN function or NULL if not applicable 32 | NULL, // name of the RINIT function or NULL if not applicable 33 | NULL, // name of the RSHUTDOWN function or NULL if not applicable 34 | PHP_MINFO(tensile), 35 | #if ZEND_MODULE_API_NO >= 20010901 36 | TENSILE_VERSION, 37 | #endif 38 | STANDARD_MODULE_PROPERTIES 39 | }; 40 | 41 | ZEND_GET_MODULE(tensile) 42 | 43 | static PHP_MINFO_FUNCTION(tensile) 44 | { 45 | 46 | php_info_print_table_start(); 47 | php_info_print_table_row(2, "Tensorflow Support", "enabled"); 48 | php_info_print_table_row(2, "Build", TENSILE_VERSION); 49 | php_info_print_table_row(2, "Release", TENSILE_FLAVOR); 50 | php_info_print_table_end(); 51 | 52 | DISPLAY_INI_ENTRIES(); 53 | } 54 | 55 | 56 | static PHP_FUNCTION(debug) 57 | { 58 | #if PHP_MAJOR_VERSION < 7 59 | RETURN_STRING("Hello Dave",0); 60 | #else 61 | RETURN_STRING("Hello Dave"); 62 | #endif 63 | 64 | } 65 | 66 | static PHP_MINIT_FUNCTION(tensile) 67 | { 68 | REGISTER_NS_STRING_CONSTANT("Tensile", "VERSION", (char *) TF_Version(), CONST_PERSISTENT | CONST_CS); 69 | 70 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_FLOAT", 1, CONST_PERSISTENT | CONST_CS); 71 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_DOUBLE", 2, CONST_PERSISTENT | CONST_CS); 72 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_INT32", 3, CONST_PERSISTENT | CONST_CS); 73 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_UINT8", 4, CONST_PERSISTENT | CONST_CS); 74 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_INT16", 5, CONST_PERSISTENT | CONST_CS); 75 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_INT8", 6, CONST_PERSISTENT | CONST_CS); 76 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_STRING", 7, CONST_PERSISTENT | CONST_CS); 77 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_COMPLEX64", 8, CONST_PERSISTENT | CONST_CS); 78 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_COMPLEX", 8, CONST_PERSISTENT | CONST_CS); 79 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_INT64", 9, CONST_PERSISTENT | CONST_CS); 80 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_BOOL", 10, CONST_PERSISTENT | CONST_CS); 81 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_QINT8", 11, CONST_PERSISTENT | CONST_CS); 82 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_QUINT8", 12, CONST_PERSISTENT | CONST_CS); 83 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_QINT32", 13, CONST_PERSISTENT | CONST_CS); 84 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_BFLOAT16", 14, CONST_PERSISTENT | CONST_CS); 85 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_QINT16", 15, CONST_PERSISTENT | CONST_CS); 86 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_QUINT16", 16, CONST_PERSISTENT | CONST_CS); 87 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_UINT16", 17, CONST_PERSISTENT | CONST_CS); 88 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_COMPLEX128", 18, CONST_PERSISTENT | CONST_CS); 89 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_HALF", 19, CONST_PERSISTENT | CONST_CS); 90 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_RESOURCE", 20, CONST_PERSISTENT | CONST_CS); 91 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_VARIANT", 21, CONST_PERSISTENT | CONST_CS); 92 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_UINT32", 22, CONST_PERSISTENT | CONST_CS); 93 | REGISTER_NS_LONG_CONSTANT("Tensile", "DTYPE_UINT64", 23, CONST_PERSISTENT | CONST_CS); 94 | 95 | return SUCCESS; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/class/tf_tensor.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_tensor.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Tensor = NULL; 6 | zend_object_handlers oh_TF_Tensor; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_Tensor, __construct); 10 | static PHP_METHOD(TensorFlow_Tensor, __destruct); 11 | static PHP_METHOD(TensorFlow_Tensor, getDtype); 12 | 13 | // argument info 14 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_tensor___construct, 0, 0, 1) 15 | ZEND_ARG_INFO(0, dtype) 16 | ZEND_ARG_ARRAY_INFO(0, dims, 1) 17 | ZEND_ARG_ARRAY_INFO(0, data, 1) 18 | ZEND_END_ARG_INFO() 19 | 20 | // methods 21 | static zend_function_entry tf_tensor_methods[] = { 22 | PHP_ME(TensorFlow_Tensor, __construct, arginfo_tf_tensor___construct, ZEND_ACC_PUBLIC) 23 | PHP_ME(TensorFlow_Tensor, __destruct, NULL, ZEND_ACC_PUBLIC) 24 | PHP_ME(TensorFlow_Tensor, getDtype, NULL, ZEND_ACC_PUBLIC) 25 | PHP_FE_END 26 | }; 27 | 28 | CA_OBJECT_CREATE(tensor, t_tf_tensor, t_tf_tensor_object, oh_TF_Tensor) 29 | CA_OBJECT_FREE(tensor, t_tf_tensor, t_tf_tensor_object) 30 | 31 | void define_tf_tensor_class() 32 | { 33 | DEFINE_CLASS(Tensor, tensor, ce_TF_Tensor, oh_TF_Tensor) 34 | } 35 | 36 | // extern TF_Tensor* TF_AllocateTensor(TF_DataType, const int64_t* dims, int num_dims, size_t len); 37 | static PHP_METHOD(TensorFlow_Tensor, __construct) 38 | { 39 | zend_long dtype; 40 | zval* dims; 41 | zval* data; 42 | 43 | ZEND_PARSE_PARAMETERS_START(1, 3) 44 | Z_PARAM_LONG(dtype) 45 | Z_PARAM_OPTIONAL 46 | Z_PARAM_ARRAY_EX(dims, 1, 0) 47 | Z_PARAM_ARRAY_EX(data, 1, 0) 48 | ZEND_PARSE_PARAMETERS_END(); 49 | 50 | if (!valid_dtype(dtype)) { 51 | zend_throw_exception(spl_ce_InvalidArgumentException, "dtype must be from 1 to 20", 0); 52 | return; 53 | } 54 | 55 | 56 | TF_DataType tf_dtype = (TF_DataType) dtype; 57 | 58 | int64_t* tf_dims = NULL; 59 | int tf_num_dims = 0; 60 | size_t tf_len = tf_dtype_sizeof(tf_dtype); 61 | 62 | if (dims != NULL) { 63 | HashTable *dims_table = Z_ARRVAL_P(dims); 64 | tf_num_dims = zend_hash_num_elements(dims_table); // count of array 65 | 66 | if (tf_num_dims > 0) { 67 | tf_dims = (int64_t*)emalloc(sizeof(int64_t) * tf_num_dims); 68 | 69 | HashPosition pos; 70 | zval* element; 71 | int index = 0; 72 | 73 | zend_hash_internal_pointer_reset_ex(dims_table, &pos); 74 | while (zend_hash_has_more_elements_ex(dims_table, &pos) == SUCCESS) { 75 | if (!(element = zend_hash_get_current_data_ex(dims_table, &pos))) { 76 | zend_throw_exception(spl_ce_InvalidArgumentException, "dims something wrong", 0); 77 | return; 78 | } 79 | if (zval_get_type(element) != IS_LONG) { 80 | zend_throw_exception(spl_ce_InvalidArgumentException, "dims must be array of integer", 0); 81 | return; 82 | } 83 | // multi equal tf_len and insert tf_dims 84 | tf_len *= tf_dims[index] = element->value.lval; 85 | // php_printf("%d \n", element->value.lval); 86 | zend_hash_move_forward_ex(dims_table, &pos); 87 | 88 | index++; 89 | } 90 | } 91 | } 92 | 93 | // php_printf("dtype ? %d\n", tf_dtype); 94 | // int i; 95 | // for (i = 0; i < tf_num_dims; i++) { 96 | // php_printf("dims[%d] ? %d\n", i, tf_dims[i]); 97 | // } 98 | // php_printf("tf_num_dims ? %d\n", tf_num_dims); 99 | // php_printf("len ? %d\n", tf_len); 100 | 101 | // this 102 | t_tf_tensor_object* intern; 103 | t_tf_tensor* php_tf_tensor; 104 | int len = 0; 105 | 106 | intern = TF_TENSOR_P_ZV(getThis()); 107 | php_tf_tensor = intern->ptr; 108 | php_tf_tensor->src = TF_AllocateTensor(tf_dtype, tf_dims, tf_num_dims, tf_len); 109 | } 110 | 111 | // extern void TF_DeleteTensor(TF_Tensor*); 112 | static PHP_METHOD(TensorFlow_Tensor, __destruct) 113 | { 114 | t_tf_tensor_object* intern = TF_TENSOR_P_ZV(getThis()); 115 | t_tf_tensor* node = intern->ptr; 116 | 117 | TF_DeleteTensor(node->src); 118 | } 119 | 120 | // extern TF_DataType TF_TensorType(const TF_Tensor*); 121 | static PHP_METHOD(TensorFlow_Tensor, getDtype) 122 | { 123 | t_tf_tensor_object* intern = TF_TENSOR_P_ZV(getThis()); 124 | t_tf_tensor* node = intern->ptr; 125 | 126 | RETURN_LONG(TF_TensorType(node->src)); 127 | } 128 | -------------------------------------------------------------------------------- /src/class/tf_status.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_status.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Status = NULL; 6 | zend_object_handlers oh_TF_Status; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_Status, __construct); 10 | static PHP_METHOD(TensorFlow_Status, __destruct); 11 | static PHP_METHOD(TensorFlow_Status, setCode); 12 | static PHP_METHOD(TensorFlow_Status, getCode); 13 | static PHP_METHOD(TensorFlow_Status, getMessage); 14 | 15 | // argument info 16 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_status_setCode, 0, 0, 1) 17 | ZEND_ARG_INFO(0, code) 18 | ZEND_ARG_INFO(0, message) 19 | ZEND_END_ARG_INFO() 20 | 21 | 22 | // methods 23 | static zend_function_entry tf_status_methods[] = { 24 | PHP_ME(TensorFlow_Status, __construct, NULL, ZEND_ACC_PUBLIC) 25 | PHP_ME(TensorFlow_Status, __destruct, NULL, ZEND_ACC_PUBLIC) 26 | PHP_ME(TensorFlow_Status, setCode, arginfo_tf_status_setCode, ZEND_ACC_PUBLIC) 27 | PHP_ME(TensorFlow_Status, getCode, NULL, ZEND_ACC_PUBLIC) 28 | PHP_ME(TensorFlow_Status, getMessage, NULL, ZEND_ACC_PUBLIC) 29 | PHP_FE_END 30 | }; 31 | 32 | CA_OBJECT_CREATE(status, t_tf_status, t_tf_status_object, oh_TF_Status) 33 | CA_OBJECT_FREE(status, t_tf_status, t_tf_status_object) 34 | 35 | void define_tf_status_class() 36 | { 37 | DEFINE_CLASS(Status, status, ce_TF_Status, oh_TF_Status) 38 | 39 | #define TF_STATUS_CLASS_CONST(name, value) zend_declare_class_constant_long(ce_TF_Status, name, sizeof(name) - 1, value); 40 | 41 | TF_STATUS_CLASS_CONST("CODE_OK", 0); 42 | TF_STATUS_CLASS_CONST("CODE_CANCELLED", 1); 43 | TF_STATUS_CLASS_CONST("CODE_UNKNOWN", 2); 44 | TF_STATUS_CLASS_CONST("CODE_INVALID_ARGUMENT", 3); 45 | TF_STATUS_CLASS_CONST("CODE_DEADLINE_EXCEEDED", 4); 46 | TF_STATUS_CLASS_CONST("CODE_NOT_FOUND", 5); 47 | TF_STATUS_CLASS_CONST("CODE_ALREADY_EXISTS", 6); 48 | TF_STATUS_CLASS_CONST("CODE_PERMISSION_DENIED", 7); 49 | TF_STATUS_CLASS_CONST("CODE_RESOURCE_EXHAUSTED", 8); 50 | TF_STATUS_CLASS_CONST("CODE_FAILED_PRECONDITION", 9); 51 | TF_STATUS_CLASS_CONST("CODE_ABORTED", 10); 52 | TF_STATUS_CLASS_CONST("CODE_OUT_OF_RANGE", 11); 53 | TF_STATUS_CLASS_CONST("CODE_UNIMPLEMENTED", 12); 54 | TF_STATUS_CLASS_CONST("CODE_INTERNAL", 13); 55 | TF_STATUS_CLASS_CONST("CODE_UNAVAILABLE", 14); 56 | TF_STATUS_CLASS_CONST("CODE_DATA_LOSS", 15); 57 | TF_STATUS_CLASS_CONST("CODE_UNAUTHENTICATED", 16); 58 | } 59 | 60 | static PHP_METHOD(TensorFlow_Status, __construct) 61 | { 62 | t_tf_status_object* intern = TF_STATUS_P_ZV(getThis()); 63 | t_tf_status* node = intern->ptr; 64 | 65 | node->src = TF_NewStatus(); 66 | } 67 | 68 | static PHP_METHOD(TensorFlow_Status, __destruct) 69 | { 70 | t_tf_status_object* intern = TF_STATUS_P_ZV(getThis()); 71 | t_tf_status* node = intern->ptr; 72 | 73 | TF_DeleteStatus(node->src); 74 | } 75 | 76 | // void TF_SetStatus(TF_Status* s, TF_Code code, const char* message); 77 | static PHP_METHOD(TensorFlow_Status, setCode) 78 | { 79 | // arguments 80 | int code; 81 | char* message = NULL; 82 | size_t message_len; 83 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &code, &message, &message_len) == FAILURE) { 84 | RETURN_NULL(); 85 | return; 86 | } 87 | // ZEND_PARSE_PARAMETERS_START(1, 2) 88 | // Z_PARAM_LONG(code) 89 | // Z_PARAM_OPTIONAL 90 | // Z_PARAM_STR(message) 91 | // ZEND_PARSE_PARAMETERS_END(); 92 | 93 | t_tf_status_object* intern = TF_STATUS_P_ZV(getThis()); 94 | t_tf_status* node = intern->ptr; 95 | TF_Status* tf_status = node->src; 96 | 97 | if (message == NULL) { 98 | TF_SetStatus(tf_status, code, ""); 99 | } else { 100 | TF_SetStatus(tf_status, code, message); 101 | } 102 | } 103 | 104 | // extern TF_Code TF_GetCode(const TF_Status* s); 105 | static PHP_METHOD(TensorFlow_Status, getCode) 106 | { 107 | if (ZEND_NUM_ARGS() != 0) { 108 | WRONG_PARAM_COUNT; 109 | } 110 | 111 | // this 112 | t_tf_status_object* intern = TF_STATUS_P_ZV(getThis()); 113 | t_tf_status* node = intern->ptr; 114 | TF_Status* tf_status = node->src; 115 | 116 | RETURN_LONG(TF_GetCode(tf_status)); 117 | } 118 | 119 | 120 | // extern const char* TF_Message(const TF_Status* s); 121 | static PHP_METHOD(TensorFlow_Status, getMessage) 122 | { 123 | if (ZEND_NUM_ARGS() != 0) { 124 | WRONG_PARAM_COUNT; 125 | } 126 | 127 | // this 128 | t_tf_status_object* intern = TF_STATUS_P_ZV(getThis()); 129 | t_tf_status* node = intern->ptr; 130 | TF_Status* tf_status = node->src; 131 | 132 | RETURN_STRING(TF_Message(tf_status)); 133 | } 134 | -------------------------------------------------------------------------------- /src/class/tf_session.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_session.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_Session = NULL; 6 | zend_object_handlers oh_TF_Session; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_Session, __construct); 10 | static PHP_METHOD(TensorFlow_Session, __destruct); 11 | static PHP_METHOD(TensorFlow_Session, close); 12 | 13 | // argument info 14 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_session___construct, 0, 0, 3) 15 | ZEND_ARG_INFO(0, graph) 16 | ZEND_ARG_INFO(0, sessionOptions) 17 | ZEND_ARG_INFO(0, status) 18 | ZEND_END_ARG_INFO() 19 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_session_close, 0, 0, 1) 20 | ZEND_ARG_INFO(0, status) 21 | ZEND_END_ARG_INFO() 22 | 23 | // methods 24 | static zend_function_entry tf_session_methods[] = { 25 | PHP_ME(TensorFlow_Session, __construct, arginfo_tf_session___construct, ZEND_ACC_PUBLIC) 26 | PHP_ME(TensorFlow_Session, __destruct, NULL, ZEND_ACC_PUBLIC) 27 | PHP_ME(TensorFlow_Session, close, arginfo_tf_session_close, ZEND_ACC_PUBLIC) 28 | PHP_FE_END 29 | }; 30 | 31 | CA_OBJECT_CREATE(session, t_tf_session, t_tf_session_object, oh_TF_Session) 32 | CA_OBJECT_FREE(session, t_tf_session, t_tf_session_object) 33 | 34 | void define_tf_session_class() 35 | { 36 | DEFINE_CLASS(Session, session, ce_TF_Session, oh_TF_Session) 37 | } 38 | 39 | // extern TF_Session* TF_NewSession(TF_Graph* graph, const TF_SessionOptions* opts, 40 | // TF_Status* status); 41 | static PHP_METHOD(TensorFlow_Session, __construct) 42 | { 43 | zval* graph; 44 | zval* sessionOptions; 45 | zval* status; 46 | 47 | ZEND_PARSE_PARAMETERS_START(3, 3) 48 | Z_PARAM_OBJECT_OF_CLASS_EX(graph, ce_TF_Graph, 0, 1) 49 | Z_PARAM_OBJECT_OF_CLASS_EX(sessionOptions, ce_TF_SessionOptions, 0, 1) 50 | Z_PARAM_OBJECT_OF_CLASS_EX(status, ce_TF_Status, 0, 1) 51 | ZEND_PARSE_PARAMETERS_END(); 52 | 53 | t_tf_session_object* intern = TF_SESSION_P_ZV(getThis()); 54 | t_tf_session* node = intern->ptr; 55 | 56 | node->src = TF_NewSession( 57 | TF_GRAPH_P_ZV(graph)->ptr->src, 58 | TF_SESSION_OPTIONS_P_ZV(sessionOptions)->ptr->src, 59 | TF_STATUS_P_ZV(status)->ptr->src 60 | ); 61 | } 62 | 63 | // extern void TF_DeleteSession(TF_Session*); 64 | static PHP_METHOD(TensorFlow_Session, __destruct) 65 | { 66 | t_tf_session_object* intern = TF_SESSION_P_ZV(getThis()); 67 | t_tf_session* node = intern->ptr; 68 | 69 | // TF_DeleteSession(node->src); 70 | } 71 | 72 | // extern void TF_CloseSession(TF_Session*, TF_Status* status); 73 | static PHP_METHOD(TensorFlow_Session, close) 74 | { 75 | zval* status; 76 | 77 | ZEND_PARSE_PARAMETERS_START(1, 1) 78 | Z_PARAM_OBJECT_OF_CLASS_EX(status, ce_TF_Status, 0, 1) 79 | ZEND_PARSE_PARAMETERS_END(); 80 | 81 | // php_printf("target : %s\n", target->val); 82 | 83 | t_tf_session_object* intern = TF_SESSION_P_ZV(getThis()); 84 | t_tf_session* node = intern->ptr; 85 | 86 | TF_CloseSession(node->src, TF_STATUS_P_ZV(status)->ptr->src); 87 | } 88 | 89 | // // Destroy a session object. 90 | // // 91 | // // Even if error information is recorded in *status, this call discards all 92 | // // local resources associated with the session. The session may not be used 93 | // // during or after this call (and the session drops its reference to the 94 | // // corresponding graph). 95 | // extern void TF_DeleteSession(TF_Session*, TF_Status* status); 96 | 97 | // // Run the graph associated with the session starting with the supplied inputs 98 | // // (inputs[0,ninputs-1] with corresponding values in input_values[0,ninputs-1]). 99 | // // 100 | // // Any NULL and non-NULL value combinations for (`run_options`, 101 | // // `run_metadata`) are valid. 102 | // // 103 | // // - `run_options` may be NULL, in which case it will be ignored; or 104 | // // non-NULL, in which case it must point to a `TF_Buffer` containing the 105 | // // serialized representation of a `RunOptions` protocol buffer. 106 | // // - `run_metadata` may be NULL, in which case it will be ignored; or 107 | // // non-NULL, in which case it must point to an empty, freshly allocated 108 | // // `TF_Buffer` that may be updated to contain the serialized representation 109 | // // of a `RunMetadata` protocol buffer. 110 | // // 111 | // // The caller retains ownership of `input_values` (which can be deleted using 112 | // // TF_DeleteTensor). The caller also retains ownership of `run_options` and/or 113 | // // `run_metadata` (when not NULL) and should manually call TF_DeleteBuffer on 114 | // // them. 115 | // // 116 | // // On success, the tensors corresponding to outputs[0,noutputs-1] are placed in 117 | // // output_values[]. Ownership of the elements of output_values[] is transferred 118 | // // to the caller, which must eventually call TF_DeleteTensor on them. 119 | // // 120 | // // On failure, output_values[] contains NULLs. 121 | // extern void TF_SessionRun(TF_Session* session, 122 | // // RunOptions 123 | // const TF_Buffer* run_options, 124 | // // Input tensors 125 | // const TF_Output* inputs, 126 | // TF_Tensor* const* input_values, int ninputs, 127 | // // Output tensors 128 | // const TF_Output* outputs, TF_Tensor** output_values, 129 | // int noutputs, 130 | // // Target operations 131 | // const TF_Operation* const* target_opers, int ntargets, 132 | // // RunMetadata 133 | // TF_Buffer* run_metadata, 134 | // // Output status 135 | // TF_Status*); 136 | 137 | // // Set up the graph with the intended feeds (inputs) and fetches (outputs) for a 138 | // // sequence of partial run calls. 139 | // // 140 | // // On success, returns a handle that is used for subsequent PRun calls. 141 | // // 142 | // // On failure, out_status contains a tensorflow::Status with an error 143 | // // message. 144 | // // NOTE: This is EXPERIMENTAL and subject to change. 145 | // extern void TF_SessionPRunSetup(TF_Session*, 146 | // // Input names 147 | // const TF_Output* inputs, int ninputs, 148 | // // Output names 149 | // const TF_Output* outputs, int noutputs, 150 | // // Target operations 151 | // const TF_Operation* const* target_opers, 152 | // int ntargets, 153 | // // Output handle 154 | // const char** handle, 155 | // // Output status 156 | // TF_Status*); 157 | 158 | // // Continue to run the graph with additional feeds and fetches. The 159 | // // execution state is uniquely identified by the handle. 160 | // // NOTE: This is EXPERIMENTAL and subject to change. 161 | // extern void TF_SessionPRun(TF_Session*, const char* handle, 162 | // // Input tensors 163 | // const TF_Output* inputs, 164 | // TF_Tensor* const* input_values, int ninputs, 165 | // // Output tensors 166 | // const TF_Output* outputs, TF_Tensor** output_values, 167 | // int noutputs, 168 | // // Target operations 169 | // const TF_Operation* const* target_opers, 170 | // int ntargets, 171 | // // Output status 172 | // TF_Status*); 173 | -------------------------------------------------------------------------------- /stubs/tensile.php: -------------------------------------------------------------------------------- 1 | 5 | * @link https://github.com/absalomedia/tensile 6 | */ 7 | 8 | namespace Tensile 9 | { 10 | // extern const char* TF_Version(); 11 | const VERSION; 12 | 13 | // typedef enum { ... } TF_DataType 14 | const DTYPE_FLOAT = 1; 15 | const DTYPE_DOUBLE = 2; 16 | const DTYPE_INT32 = 3; 17 | const DTYPE_UINT8 = 4; 18 | const DTYPE_INT16 = 5; 19 | const DTYPE_INT8 = 6; 20 | const DTYPE_STRING = 7; 21 | const DTYPE_COMPLEX64 = 8; 22 | const DTYPE_COMPLEX = 8; 23 | const DTYPE_INT64 = 9; 24 | const DTYPE_BOOL = 10; 25 | const DTYPE_QINT8 = 11; 26 | const DTYPE_QUINT8 = 12; 27 | const DTYPE_QINT32 = 13; 28 | const DTYPE_BFLOAT16 = 14; 29 | const DTYPE_QINT16 = 15; 30 | const DTYPE_QUINT16 = 16; 31 | const DTYPE_UINT16 = 17; 32 | const DTYPE_COMPLEX128 = 18; 33 | const DTYPE_HALF = 19; 34 | const DTYPE_RESOURCE = 20; 35 | 36 | // typedef struct TF_Status TF_Status; 37 | class Status 38 | { 39 | // typedef enum { ... } TF_Code; 40 | const CODE_OK = 0; 41 | const CODE_CANCELLED = 1; 42 | const CODE_UNKNOWN = 2; 43 | const CODE_INVALID_ARGUMENT = 3; 44 | const CODE_DEADLINE_EXCEEDED = 4; 45 | const CODE_NOT_FOUND = 5; 46 | const CODE_ALREADY_EXISTS = 6; 47 | const CODE_PERMISSION_DENIED = 7 ; 48 | const CODE_RESOURCE_EXHAUSTED = 8; 49 | const CODE_FAILED_PRECONDITION = 9; 50 | const CODE_ABORTED = 10; 51 | const CODE_OUT_OF_RANGE = 11; 52 | const CODE_UNIMPLEMENTED = 12; 53 | const CODE_INTERNAL = 13; 54 | const CODE_UNAVAILABLE = 14; 55 | const CODE_DATA_LOSS = 15; 56 | const CODE_UNAUTHENTICATED = 16; 57 | 58 | // extern TF_Status* TF_NewStatus(); 59 | public function __construct(); 60 | 61 | // extern void TF_DeleteStatus(TF_Status*); 62 | public function __destruct(); 63 | 64 | // extern void TF_SetStatus(TF_Status* s, TF_Code code, const char* msg); 65 | public function setCode(int $code, string $message = ""): void; 66 | 67 | // extern TF_Code TF_GetCode(const TF_Status* s); 68 | public function getCode(): int; 69 | 70 | // extern const char* TF_Message(const TF_Status* s); 71 | public function getMessage(): string; 72 | } 73 | 74 | /* 75 | * typedef struct { 76 | * const void* data; 77 | * size_t length; 78 | * void (*data_deallocator)(void* data, size_t length); 79 | * } TF_Buffer; 80 | */ 81 | class Buffer 82 | { 83 | // extern TF_Buffer* TF_NewBufferFromString(const void* proto, size_t proto_len); 84 | // extern TF_Buffer* TF_NewBuffer(); 85 | public function __construct(string $buffer = null); 86 | 87 | // extern void TF_DeleteBuffer(TF_Buffer*); 88 | public function __destruct(); 89 | 90 | // extern TF_Buffer TF_GetBuffer(TF_Buffer* buffer); 91 | // return TF_GetBuffer( ... ).data 92 | public function __toString(): string; 93 | } 94 | 95 | // typedef struct TF_Tensor TF_Tensor; 96 | class Tensor 97 | { 98 | // extern TF_Tensor* TF_AllocateTensor(TF_DataType, const int64_t* dims, 99 | // int num_dims, size_t len); 100 | public function __construct(int $dtype, array $dims = null); 101 | 102 | // extern void TF_DeleteTensor(TF_Tensor*); 103 | public function __destruct(); 104 | 105 | // extern TF_DataType TF_TensorType(const TF_Tensor*); 106 | public function getDtype(): int; 107 | } 108 | 109 | // typedef struct TF_SessionOptions TF_SessionOptions; 110 | class SessionOptions 111 | { 112 | // extern TF_SessionOptions* TF_NewSessionOptions(); 113 | public function __construct(); 114 | 115 | // extern void TF_DeleteSessionOptions(TF_SessionOptions*); 116 | public function __destruct(); 117 | 118 | /** 119 | * extern void TF_SetTarget(TF_SessionOptions* options, const char* target); 120 | * @param string $target "local", ip:port or host:port 121 | */ 122 | public function setTarget(string $target); 123 | } 124 | 125 | // typedef struct TF_Graph TF_Graph; 126 | class Graph 127 | { 128 | /** 129 | * extern TF_Graph* TF_NewGraph(); 130 | */ 131 | public function __construct(); 132 | 133 | /** 134 | * extern void TF_DeleteGraph(TF_Graph*); 135 | */ 136 | public function __destruct(); 137 | } 138 | 139 | // typedef struct TF_OperationDescription TF_OperationDescription; 140 | class OperationDescription 141 | { 142 | /** 143 | * extern TF_OperationDescription* TF_NewOperation(TF_Graph* graph, 144 | * const char* op_type, 145 | * const char* oper_name); 146 | * 147 | * @param Graph $graph 148 | * @param string $operationType "Const" 149 | * @param string $operationName 150 | */ 151 | public function __construct(Graph $graph, string $operationType, string $operationName); 152 | 153 | /** 154 | * extern void TF_SetDevice(TF_OperationDescription* desc, const char* device); 155 | */ 156 | public function setDevice(string $device); 157 | 158 | /** 159 | * extern void TF_SetAttrInt(TF_OperationDescription* desc, const char* attr_name, 160 | * int64_t value); 161 | */ 162 | public function setAttrInt(string $name, int $value); 163 | 164 | /** 165 | * extern void TF_SetAttrIntList(TF_OperationDescription* desc, 166 | * const char* attr_name, const int64_t* values, 167 | * int num_values); 168 | */ 169 | public function setAttrIntList(string $name, int[] $values); 170 | 171 | /** 172 | * extern void TF_SetAttrFloat(TF_OperationDescription* desc, 173 | * const char* attr_name, float value); 174 | */ 175 | public function setAttrFloat(string $name, float $value); 176 | 177 | /** 178 | * extern void TF_SetAttrFloatList(TF_OperationDescription* desc, 179 | * const char* attr_name, const float* values, 180 | * int num_values); 181 | */ 182 | public function setAttrFloatList(string $name, float[] $values); 183 | 184 | /** 185 | * extern void TF_SetAttrBool(TF_OperationDescription* desc, const char* attr_name, 186 | * unsigned char value); 187 | */ 188 | public function setAttrBool(string $name, bool $value); 189 | 190 | /** 191 | * extern void TF_SetAttrBoolList(TF_OperationDescription* desc, 192 | * const char* attr_name, 193 | * const unsigned char* values, int num_values); 194 | */ 195 | public function setAttrBoolList(string $name, bool[] $values); 196 | 197 | /** 198 | * extern void TF_SetAttrType(TF_OperationDescription* desc, const char* attr_name, 199 | * TF_DataType value); 200 | */ 201 | public function setAttrType(string $name, int $dtype); 202 | 203 | /** 204 | * extern void TF_SetAttrTypeList(TF_OperationDescription* desc, 205 | * const char* attr_name, const TF_DataType* values, 206 | * int num_values); 207 | */ 208 | public function setAttrTypeList(string $name, int[] $dtypes); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/class/tf_operation.h: -------------------------------------------------------------------------------- 1 | // // Operation that has been added to the graph. Valid until the graph is 2 | // // deleted -- in particular adding a new operation to the graph does not 3 | // // invalidate old TF_Operation* pointers. 4 | // typedef struct TF_Operation TF_Operation; 5 | 6 | // // TF_Operation functions. Operations are immutable once created, so 7 | // // these are all query functions. 8 | 9 | // extern const char* TF_OperationName(TF_Operation* oper); 10 | // extern const char* TF_OperationOpType(TF_Operation* oper); 11 | // extern const char* TF_OperationDevice(TF_Operation* oper); 12 | 13 | // extern int TF_OperationNumOutputs(TF_Operation* oper); 14 | // extern TF_DataType TF_OperationOutputType(TF_Output oper_out); 15 | // extern int TF_OperationOutputListLength(TF_Operation* oper, 16 | // const char* arg_name, 17 | // TF_Status* status); 18 | 19 | // extern int TF_OperationNumInputs(TF_Operation* oper); 20 | // extern TF_DataType TF_OperationInputType(TF_Input oper_in); 21 | // extern int TF_OperationInputListLength(TF_Operation* oper, const char* arg_name, 22 | // TF_Status* status); 23 | 24 | 25 | // // Get the number of control inputs to an operation. 26 | // extern int TF_OperationNumControlInputs(TF_Operation* oper); 27 | 28 | // // Get list of all control inputs to an operation. `control_inputs` must 29 | // // point to an array of length `max_control_inputs` (ideally set to 30 | // // TF_OperationNumControlInputs(oper)). Returns the number of control 31 | // // inputs (should match TF_OperationNumControlInputs(oper)). 32 | // extern int TF_OperationGetControlInputs(TF_Operation* oper, 33 | // TF_Operation** control_inputs, 34 | // int max_control_inputs); 35 | 36 | // // Get the number of operations that have `*oper` as a control input. 37 | // // Note that this number can change when new operations are added to 38 | // // the graph. 39 | // extern int TF_OperationNumControlOutputs(TF_Operation* oper); 40 | 41 | // // Get the list of operations that have `*oper` as a control input. 42 | // // `control_outputs` must point to an array of length at least 43 | // // `max_control_outputs` (ideally set to 44 | // // TF_OperationNumControlOutputs(oper)). Beware that a concurrent 45 | // // modification of the graph can increase the number of control 46 | // // outputs. Returns the number of control outputs (should match 47 | // // TF_OperationNumControlOutputs(oper)). 48 | // extern int TF_OperationGetControlOutputs(TF_Operation* oper, 49 | // TF_Operation** control_outputs, 50 | // int max_control_outputs); 51 | 52 | // // Fills in `value` with the value of the attribute `attr_name`. `value` must 53 | // // point to an array of length at least `max_length` (ideally set to 54 | // // TF_AttrMetadata.total_size from TF_OperationGetAttrMetadata(oper, 55 | // // attr_name)). 56 | // extern void TF_OperationGetAttrString(TF_Operation* oper, const char* attr_name, 57 | // void* value, size_t max_length, 58 | // TF_Status* status); 59 | 60 | // // Get the list of strings in the value of the attribute `attr_name`. Fills in 61 | // // `values` and `lengths`, each of which must point to an array of length at 62 | // // least `max_values`. 63 | // // 64 | // // The elements of values will point to addresses in `storage` which must be at 65 | // // least `storage_size` bytes in length. Ideally, max_values would be set to 66 | // // TF_AttrMetadata.list_size and `storage` would be at least 67 | // // TF_AttrMetadata.total_size, obtained from TF_OperationGetAttrMetadata(oper, 68 | // // attr_name). 69 | // // 70 | // // Fails if storage_size is too small to hold the requested number of strings. 71 | // extern void TF_OperationGetAttrStringList(TF_Operation* oper, 72 | // const char* attr_name, void** values, 73 | // size_t* lengths, int max_values, 74 | // void* storage, size_t storage_size, 75 | // TF_Status* status); 76 | 77 | // extern void TF_OperationGetAttrInt(TF_Operation* oper, const char* attr_name, 78 | // int64_t* value, TF_Status* status); 79 | 80 | // // Fills in `values` with the value of the attribute `attr_name` of `oper`. 81 | // // `values` must point to an array of length at least `max_values` (ideally set 82 | // // TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper, 83 | // // attr_name)). 84 | // extern void TF_OperationGetAttrIntList(TF_Operation* oper, 85 | // const char* attr_name, int64_t* values, 86 | // int max_values, TF_Status* status); 87 | 88 | // extern void TF_OperationGetAttrFloat(TF_Operation* oper, const char* attr_name, 89 | // float* value, TF_Status* status); 90 | 91 | // // Fills in `values` with the value of the attribute `attr_name` of `oper`. 92 | // // `values` must point to an array of length at least `max_values` (ideally set 93 | // // to TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper, 94 | // // attr_name)). 95 | // extern void TF_OperationGetAttrFloatList(TF_Operation* oper, 96 | // const char* attr_name, float* values, 97 | // int max_values, TF_Status* status); 98 | 99 | // extern void TF_OperationGetAttrBool(TF_Operation* oper, const char* attr_name, 100 | // unsigned char* value, TF_Status* status); 101 | 102 | // // Fills in `values` with the value of the attribute `attr_name` of `oper`. 103 | // // `values` must point to an array of length at least `max_values` (ideally set 104 | // // to TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper, 105 | // // attr_name)). 106 | // extern void TF_OperationGetAttrBoolList(TF_Operation* oper, 107 | // const char* attr_name, 108 | // unsigned char* values, int max_values, 109 | // TF_Status* status); 110 | 111 | // extern void TF_OperationGetAttrType(TF_Operation* oper, const char* attr_name, 112 | // TF_DataType* value, TF_Status* status); 113 | 114 | // // Fills in `values` with the value of the attribute `attr_name` of `oper`. 115 | // // `values` must point to an array of length at least `max_values` (ideally set 116 | // // to TF_AttrMetadata.list_size from TF_OperationGetAttrMetadata(oper, 117 | // // attr_name)). 118 | // extern void TF_OperationGetAttrTypeList(TF_Operation* oper, 119 | // const char* attr_name, 120 | // TF_DataType* values, int max_values, 121 | // TF_Status* status); 122 | 123 | // // Fills in `value` with the value of the attribute `attr_name` of `oper`. 124 | // // `values` must point to an array of length at least `num_dims` (ideally set to 125 | // // TF_Attr_Meta.size from TF_OperationGetAttrMetadata(oper, attr_name)). 126 | // extern void TF_OperationGetAttrShape(TF_Operation* oper, const char* attr_name, 127 | // int64_t* value, int num_dims, 128 | // TF_Status* status); 129 | 130 | // // Fills in `dims` with the list of shapes in the attribute `attr_name` of 131 | // // `oper` and `num_dims` with the corresponding number of dimensions. On return, 132 | // // for every i where `num_dims[i]` > 0, `dims[i]` will be an array of 133 | // // `num_dims[i]` elements. A value of -1 for `num_dims[i]` indicates that the 134 | // // i-th shape in the list is unknown. 135 | // // 136 | // // The elements of `dims` will point to addresses in `storage` which must be 137 | // // large enough to hold at least `storage_size` int64_ts. Ideally, `num_shapes` 138 | // // would be set to TF_AttrMetadata.list_size and `storage_size` would be set to 139 | // // TF_AttrMetadata.total_size from TF_OperationGetAttrMetadata(oper, 140 | // // attr_name). 141 | // // 142 | // // Fails if storage_size is insufficient to hold the requested shapes. 143 | // extern void TF_OperationGetAttrShapeList(TF_Operation* oper, 144 | // const char* attr_name, int64_t** dims, 145 | // int* num_dims, int num_shapes, 146 | // int64_t* storage, int storage_size, 147 | // TF_Status* status); 148 | 149 | // // Sets `value` to the binary-serialized TensorShapeProto of the value of 150 | // // `attr_name` attribute of `oper`'. 151 | // extern void TF_OperationGetAttrTensorShapeProto(TF_Operation* oper, 152 | // const char* attr_name, 153 | // TF_Buffer* value, 154 | // TF_Status* status); 155 | 156 | // // Fills in `values` with binary-serialized TensorShapeProto values of the 157 | // // attribute `attr_name` of `oper`. `values` must point to an array of length at 158 | // // least `num_values` (ideally set to TF_AttrMetadata.list_size from 159 | // // TF_OperationGetAttrMetadata(oper, attr_name)). 160 | // extern void TF_OperationGetAttrTensorShapeProtoList(TF_Operation* oper, 161 | // const char* attr_name, 162 | // TF_Buffer** values, 163 | // int max_values, 164 | // TF_Status* status); 165 | 166 | // // Gets the TF_Tensor valued attribute of `attr_name` of `oper`. 167 | // // 168 | // // Allocates a new TF_Tensor which the caller is expected to take 169 | // // ownership of (and can deallocate using TF_DeleteTensor). 170 | // extern void TF_OperationGetAttrTensor(TF_Operation* oper, const char* attr_name, 171 | // TF_Tensor** value, TF_Status* status); 172 | 173 | // // Fills in `values` with the TF_Tensor values of the attribute `attr_name` of 174 | // // `oper`. `values` must point to an array of TF_Tensor* of length at least 175 | // // `max_values` (ideally set to TF_AttrMetadata.list_size from 176 | // // TF_OperationGetAttrMetadata(oper, attr_name)). 177 | // // 178 | // // The caller takes ownership of all the non-null TF_Tensor* entries in `values` 179 | // // (which can be deleted using TF_DeleteTensor(values[i])). 180 | // extern void TF_OperationGetAttrTensorList(TF_Operation* oper, 181 | // const char* attr_name, 182 | // TF_Tensor** values, int max_values, 183 | // TF_Status* status); 184 | 185 | // // Sets `output_attr_value` to the binary-serialized AttrValue proto 186 | // // representation of the value of the `attr_name` attr of `oper`. 187 | // extern void TF_OperationGetAttrValueProto(TF_Operation* oper, 188 | // const char* attr_name, 189 | // TF_Buffer* output_attr_value, 190 | // TF_Status* status); 191 | 192 | // // Returns the operation in the graph with `oper_name`. Returns nullptr if 193 | // // no operation found. 194 | // extern TF_Operation* TF_GraphOperationByName(TF_Graph* graph, 195 | // const char* oper_name); 196 | 197 | 198 | // // Note: The following function may fail on very large protos in the future. 199 | 200 | // extern void TF_OperationToNodeDef(TF_Operation* oper, 201 | // TF_Buffer* output_node_def, 202 | // TF_Status* status); 203 | 204 | 205 | -------------------------------------------------------------------------------- /src/class/tf_operation_description.c: -------------------------------------------------------------------------------- 1 | 2 | #include "tf_operation_description.h" 3 | 4 | // predefine 5 | zend_class_entry *ce_TF_OperationDescription = NULL; 6 | zend_object_handlers oh_TF_OperationDescription; 7 | 8 | // methods 9 | static PHP_METHOD(TensorFlow_OperationDescription, __construct); 10 | static PHP_METHOD(TensorFlow_OperationDescription, __destruct); 11 | static PHP_METHOD(TensorFlow_OperationDescription, setDevice); 12 | 13 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrInt); 14 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrIntList); 15 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrFloat); 16 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrFloatList); 17 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrBool); 18 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrBoolList); 19 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrType); 20 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrTypeList); 21 | 22 | // argument info 23 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description___construct, 0, 0, 3) 24 | ZEND_ARG_INFO(0, graph) 25 | ZEND_ARG_INFO(0, operatorType) 26 | ZEND_ARG_INFO(0, operatorName) 27 | ZEND_END_ARG_INFO() 28 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setDevice, 0, 0, 1) 29 | ZEND_ARG_INFO(0, device) 30 | ZEND_END_ARG_INFO() 31 | 32 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrInt, 0, 0, 2) 33 | ZEND_ARG_INFO(0, name) 34 | ZEND_ARG_INFO(0, value) 35 | ZEND_END_ARG_INFO() 36 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrIntList, 0, 0, 2) 37 | ZEND_ARG_INFO(0, name) 38 | ZEND_ARG_ARRAY_INFO(0, values, 0) 39 | ZEND_END_ARG_INFO() 40 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrFloat, 0, 0, 2) 41 | ZEND_ARG_INFO(0, name) 42 | ZEND_ARG_INFO(0, value) 43 | ZEND_END_ARG_INFO() 44 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrFloatList, 0, 0, 2) 45 | ZEND_ARG_INFO(0, name) 46 | ZEND_ARG_ARRAY_INFO(0, values, 0) 47 | ZEND_END_ARG_INFO() 48 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrBool, 0, 0, 2) 49 | ZEND_ARG_INFO(0, name) 50 | ZEND_ARG_INFO(0, value) 51 | ZEND_END_ARG_INFO() 52 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrBoolList, 0, 0, 2) 53 | ZEND_ARG_INFO(0, name) 54 | ZEND_ARG_ARRAY_INFO(0, values, 0) 55 | ZEND_END_ARG_INFO() 56 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrType, 0, 0, 2) 57 | ZEND_ARG_INFO(0, name) 58 | ZEND_ARG_INFO(0, dtype) 59 | ZEND_END_ARG_INFO() 60 | ZEND_BEGIN_ARG_INFO_EX(arginfo_tf_operation_description_setAttrTypeList, 0, 0, 2) 61 | ZEND_ARG_INFO(0, name) 62 | ZEND_ARG_ARRAY_INFO(0, dtypes, 0) 63 | ZEND_END_ARG_INFO() 64 | 65 | // methods 66 | static zend_function_entry tf_operation_description_methods[] = { 67 | PHP_ME(TensorFlow_OperationDescription, __construct, 68 | arginfo_tf_operation_description___construct, ZEND_ACC_PUBLIC) 69 | PHP_ME(TensorFlow_OperationDescription, __destruct, NULL, ZEND_ACC_PUBLIC) 70 | PHP_ME(TensorFlow_OperationDescription, setDevice, 71 | arginfo_tf_operation_description_setDevice, ZEND_ACC_PUBLIC) 72 | 73 | PHP_ME(TensorFlow_OperationDescription, setAttrInt, 74 | arginfo_tf_operation_description_setAttrInt, ZEND_ACC_PUBLIC) 75 | PHP_ME(TensorFlow_OperationDescription, setAttrIntList, 76 | arginfo_tf_operation_description_setAttrIntList, ZEND_ACC_PUBLIC) 77 | PHP_ME(TensorFlow_OperationDescription, setAttrFloat, 78 | arginfo_tf_operation_description_setAttrFloat, ZEND_ACC_PUBLIC) 79 | PHP_ME(TensorFlow_OperationDescription, setAttrFloatList, 80 | arginfo_tf_operation_description_setAttrFloatList, ZEND_ACC_PUBLIC) 81 | PHP_ME(TensorFlow_OperationDescription, setAttrBool, 82 | arginfo_tf_operation_description_setAttrBool, ZEND_ACC_PUBLIC) 83 | PHP_ME(TensorFlow_OperationDescription, setAttrBoolList, 84 | arginfo_tf_operation_description_setAttrBoolList, ZEND_ACC_PUBLIC) 85 | PHP_ME(TensorFlow_OperationDescription, setAttrType, 86 | arginfo_tf_operation_description_setAttrType, ZEND_ACC_PUBLIC) 87 | PHP_ME(TensorFlow_OperationDescription, setAttrTypeList, 88 | arginfo_tf_operation_description_setAttrTypeList, ZEND_ACC_PUBLIC) 89 | PHP_FE_END 90 | }; 91 | 92 | CA_OBJECT_CREATE(operation_description, t_tf_operation_description, t_tf_operation_description_object, oh_TF_OperationDescription) 93 | CA_OBJECT_FREE(operation_description, t_tf_operation_description, t_tf_operation_description_object) 94 | 95 | void define_tf_operation_description_class() 96 | { 97 | DEFINE_CLASS(OperationDescription, operation_description, ce_TF_OperationDescription, oh_TF_OperationDescription) 98 | } 99 | 100 | // extern TF_OperationDescription* TF_NewOperation(TF_Graph* graph, 101 | // const char* op_type, const char* oper_name); 102 | static PHP_METHOD(TensorFlow_OperationDescription, __construct) 103 | { 104 | zval *graph; 105 | zend_string *operatorType; 106 | zend_string *operatorName; 107 | 108 | ZEND_PARSE_PARAMETERS_START(3, 3) 109 | Z_PARAM_OBJECT_OF_CLASS_EX(graph, ce_TF_Graph, 0, 1) // last 1 is call by ref. 110 | Z_PARAM_STR(operatorType) 111 | Z_PARAM_STR(operatorName) 112 | ZEND_PARSE_PARAMETERS_END(); 113 | 114 | // php_printf("optype : %s\n", operatorType->val); 115 | // php_printf("opname : %s\n", operatorName->val); 116 | 117 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 118 | t_tf_operation_description* node = intern->ptr; 119 | 120 | node->src = TF_NewOperation( 121 | TF_GRAPH_P_ZV(graph)->ptr->src, 122 | operatorType->val, 123 | operatorName->val 124 | ); 125 | } 126 | 127 | static PHP_METHOD(TensorFlow_OperationDescription, __destruct) 128 | { 129 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 130 | t_tf_operation_description* node = intern->ptr; 131 | // ? (node->src); 132 | } 133 | 134 | // extern void TF_SetDevice(TF_OperationDescription* desc, const char* device); 135 | static PHP_METHOD(TensorFlow_OperationDescription, setDevice) 136 | { 137 | zend_string *device; 138 | 139 | ZEND_PARSE_PARAMETERS_START(1, 1) 140 | Z_PARAM_STR(device) 141 | ZEND_PARSE_PARAMETERS_END(); 142 | 143 | // php_printf("device : %s\n", device->val); 144 | 145 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 146 | t_tf_operation_description* node = intern->ptr; 147 | 148 | TF_SetDevice(node->src, device->val); 149 | } 150 | 151 | // extern void TF_SetAttrInt(TF_OperationDescription* desc, const char* attr_name, 152 | // int64_t value); 153 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrInt) 154 | { 155 | zend_string *name; 156 | zend_long value; 157 | 158 | ZEND_PARSE_PARAMETERS_START(2, 2) 159 | Z_PARAM_STR(name) 160 | Z_PARAM_LONG(value) 161 | ZEND_PARSE_PARAMETERS_END(); 162 | 163 | // this 164 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 165 | t_tf_operation_description* node = intern->ptr; 166 | 167 | TF_SetAttrInt(node->src, name->val, value); 168 | } 169 | 170 | // extern void TF_SetAttrIntList(TF_OperationDescription* desc, 171 | // const char* attr_name, const int64_t* values, 172 | // int num_values); 173 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrIntList) 174 | { 175 | zend_string *name; 176 | zval* values; 177 | 178 | ZEND_PARSE_PARAMETERS_START(2, 2) 179 | Z_PARAM_STR(name) 180 | Z_PARAM_ARRAY(values) 181 | ZEND_PARSE_PARAMETERS_END(); 182 | 183 | 184 | int64_t* tf_values = NULL; 185 | int tf_num_values = 0; 186 | 187 | HashTable *values_table = Z_ARRVAL_P(values); 188 | tf_num_values = zend_hash_num_elements(values_table); // count of array 189 | 190 | if (tf_num_values > 0) { 191 | tf_values = (int64_t*)emalloc(sizeof(int64_t) * tf_num_values); 192 | 193 | HashPosition pos; 194 | zval* element; 195 | int index = 0; 196 | 197 | zend_hash_internal_pointer_reset_ex(values_table, &pos); 198 | while (zend_hash_has_more_elements_ex(values_table, &pos) == SUCCESS) { 199 | if (!(element = zend_hash_get_current_data_ex(values_table, &pos))) { 200 | zend_throw_exception(spl_ce_InvalidArgumentException, "values something wrong", 0); 201 | return; 202 | } 203 | if (zval_get_type(element) != IS_LONG) { 204 | zend_throw_exception(spl_ce_InvalidArgumentException, "values must be array of integer", 0); 205 | return; 206 | } 207 | // insert tf_values 208 | tf_values[index] = Z_LVAL_P(element); 209 | // php_printf("%d \n", element->value.lval); 210 | zend_hash_move_forward_ex(values_table, &pos); 211 | 212 | index++; 213 | } 214 | } 215 | 216 | // int i; 217 | // for (i = 0; i < tf_num_values; i++) { 218 | // php_printf("values[%d] ? %d\n", i, tf_values[i]); 219 | // } 220 | // php_printf("tf_num_values ? %d\n", tf_num_values); 221 | 222 | // this 223 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 224 | t_tf_operation_description* node = intern->ptr; 225 | 226 | TF_SetAttrIntList(node->src, name->val, tf_values, tf_num_values); 227 | } 228 | 229 | // extern void TF_SetAttrFloat(TF_OperationDescription* desc, 230 | // const char* attr_name, float value); 231 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrFloat) 232 | { 233 | zend_string *name; 234 | double value; 235 | 236 | ZEND_PARSE_PARAMETERS_START(2, 2) 237 | Z_PARAM_STR(name) 238 | Z_PARAM_DOUBLE(value) 239 | ZEND_PARSE_PARAMETERS_END(); 240 | 241 | // this 242 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 243 | t_tf_operation_description* node = intern->ptr; 244 | 245 | TF_SetAttrFloat(node->src, name->val, value); 246 | } 247 | 248 | // extern void TF_SetAttrFloatList(TF_OperationDescription* desc, 249 | // const char* attr_name, const float* values, 250 | // int num_values); 251 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrFloatList) 252 | { 253 | zend_string *name; 254 | zval* values; 255 | 256 | ZEND_PARSE_PARAMETERS_START(2, 2) 257 | Z_PARAM_STR(name) 258 | Z_PARAM_ARRAY(values) 259 | ZEND_PARSE_PARAMETERS_END(); 260 | 261 | 262 | float* tf_values = NULL; 263 | int tf_num_values = 0; 264 | 265 | HashTable *values_table = Z_ARRVAL_P(values); 266 | tf_num_values = zend_hash_num_elements(values_table); // count of array 267 | 268 | if (tf_num_values > 0) { 269 | tf_values = (float*)emalloc(sizeof(float) * tf_num_values); 270 | 271 | HashPosition pos; 272 | zval* element; 273 | int index = 0; 274 | 275 | zend_hash_internal_pointer_reset_ex(values_table, &pos); 276 | while (zend_hash_has_more_elements_ex(values_table, &pos) == SUCCESS) { 277 | if (!(element = zend_hash_get_current_data_ex(values_table, &pos))) { 278 | zend_throw_exception(spl_ce_InvalidArgumentException, "values something wrong", 0); 279 | return; 280 | } 281 | if (zval_get_type(element) != IS_DOUBLE) { 282 | zend_throw_exception(spl_ce_InvalidArgumentException, "values must be array of float", 0); 283 | return; 284 | } 285 | // insert tf_values 286 | tf_values[index] = Z_DVAL_P(element); 287 | // php_printf("%d \n", element->value.lval); 288 | zend_hash_move_forward_ex(values_table, &pos); 289 | 290 | index++; 291 | } 292 | } 293 | 294 | // int i; 295 | // for (i = 0; i < tf_num_values; i++) { 296 | // php_printf("values[%f] ? %d\n", i, tf_values[i]); 297 | // } 298 | // php_printf("tf_num_values ? %d\n", tf_num_values); 299 | 300 | // this 301 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 302 | t_tf_operation_description* node = intern->ptr; 303 | 304 | TF_SetAttrFloatList(node->src, name->val, tf_values, tf_num_values); 305 | } 306 | 307 | // extern void TF_SetAttrBool(TF_OperationDescription* desc, const char* attr_name, 308 | // unsigned char value); 309 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrBool) 310 | { 311 | zend_string *name; 312 | zend_bool value; 313 | 314 | ZEND_PARSE_PARAMETERS_START(2, 2) 315 | Z_PARAM_STR(name) 316 | Z_PARAM_BOOL(value) 317 | ZEND_PARSE_PARAMETERS_END(); 318 | 319 | // this 320 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 321 | t_tf_operation_description* node = intern->ptr; 322 | 323 | TF_SetAttrBool(node->src, name->val, value); 324 | } 325 | 326 | // extern void TF_SetAttrBoolList(TF_OperationDescription* desc, 327 | // const char* attr_name, 328 | // const unsigned char* values, int num_values); 329 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrBoolList) 330 | { 331 | zend_string *name; 332 | zval* values; 333 | 334 | ZEND_PARSE_PARAMETERS_START(2, 2) 335 | Z_PARAM_STR(name) 336 | Z_PARAM_ARRAY(values) 337 | ZEND_PARSE_PARAMETERS_END(); 338 | 339 | 340 | unsigned char* tf_values = NULL; 341 | int tf_num_values = 0; 342 | 343 | HashTable *values_table = Z_ARRVAL_P(values); 344 | tf_num_values = zend_hash_num_elements(values_table); // count of array 345 | 346 | if (tf_num_values > 0) { 347 | tf_values = (unsigned char*)emalloc(sizeof(unsigned char) * tf_num_values); 348 | 349 | HashPosition pos; 350 | zval* element; 351 | int index = 0; 352 | 353 | zend_hash_internal_pointer_reset_ex(values_table, &pos); 354 | while (zend_hash_has_more_elements_ex(values_table, &pos) == SUCCESS) { 355 | if (!(element = zend_hash_get_current_data_ex(values_table, &pos))) { 356 | zend_throw_exception(spl_ce_InvalidArgumentException, "values something wrong", 0); 357 | return; 358 | } 359 | if (Z_TYPE_P(element) != IS_TRUE && Z_TYPE_P(element) != IS_FALSE) { 360 | zend_throw_exception(spl_ce_InvalidArgumentException, "values must be array of bool", 0); 361 | return; 362 | } 363 | // insert tf_values 364 | if (Z_TYPE_P(element) == IS_TRUE) { 365 | tf_values[index] = 1; 366 | } else { 367 | tf_values[index] = 0; 368 | } 369 | // php_printf("%d \n", element->value.lval); 370 | zend_hash_move_forward_ex(values_table, &pos); 371 | 372 | index++; 373 | } 374 | } 375 | 376 | // int i; 377 | // for (i = 0; i < tf_num_values; i++) { 378 | // php_printf("values[%d] ? %d\n", i, tf_values[i]); 379 | // } 380 | // php_printf("tf_num_values ? %d\n", tf_num_values); 381 | 382 | // this 383 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 384 | t_tf_operation_description* node = intern->ptr; 385 | 386 | TF_SetAttrBoolList(node->src, name->val, tf_values, tf_num_values); 387 | } 388 | 389 | // extern void TF_SetAttrType(TF_OperationDescription* desc, const char* attr_name, 390 | // TF_DataType value); 391 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrType) 392 | { 393 | zend_string *name; 394 | zend_long dtype; 395 | 396 | ZEND_PARSE_PARAMETERS_START(2, 2) 397 | Z_PARAM_STR(name) 398 | Z_PARAM_LONG(dtype) 399 | ZEND_PARSE_PARAMETERS_END(); 400 | 401 | if (!valid_dtype(dtype)) { 402 | zend_throw_exception(spl_ce_InvalidArgumentException, "dtype must be from 1 to 20", 0); 403 | return; 404 | } 405 | 406 | // this 407 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 408 | t_tf_operation_description* node = intern->ptr; 409 | 410 | TF_SetAttrType(node->src, name->val, dtype); 411 | } 412 | 413 | // extern void TF_SetAttrTypeList(TF_OperationDescription* desc, 414 | // const char* attr_name, const TF_DataType* values, 415 | // int num_values); 416 | static PHP_METHOD(TensorFlow_OperationDescription, setAttrTypeList) 417 | { 418 | zend_string *name; 419 | zval* dtypes; 420 | 421 | ZEND_PARSE_PARAMETERS_START(2, 2) 422 | Z_PARAM_STR(name) 423 | Z_PARAM_ARRAY(dtypes) 424 | ZEND_PARSE_PARAMETERS_END(); 425 | 426 | 427 | TF_DataType* tf_values = NULL; 428 | int tf_num_values = 0; 429 | 430 | HashTable *values_table = Z_ARRVAL_P(dtypes); 431 | tf_num_values = zend_hash_num_elements(values_table); // count of array 432 | 433 | if (tf_num_values > 0) { 434 | tf_values = (TF_DataType*)emalloc(sizeof(TF_DataType) * tf_num_values); 435 | 436 | HashPosition pos; 437 | zval* element; 438 | int index = 0; 439 | 440 | zend_hash_internal_pointer_reset_ex(values_table, &pos); 441 | while (zend_hash_has_more_elements_ex(values_table, &pos) == SUCCESS) { 442 | if (!(element = zend_hash_get_current_data_ex(values_table, &pos))) { 443 | zend_throw_exception(spl_ce_InvalidArgumentException, "dtypes something wrong", 0); 444 | return; 445 | } 446 | if (zval_get_type(element) != IS_LONG) { 447 | zend_throw_exception(spl_ce_InvalidArgumentException, "dtypes must be array of integer", 0); 448 | return; 449 | } 450 | if (!valid_dtype(Z_LVAL_P(element))) { 451 | zend_throw_exception(spl_ce_InvalidArgumentException, "each dtype must be from 1 to 20", 0); 452 | return; 453 | } 454 | // insert tf_values 455 | tf_values[index] = Z_LVAL_P(element); 456 | // php_printf("%d \n", element->value.lval); 457 | zend_hash_move_forward_ex(values_table, &pos); 458 | 459 | index++; 460 | } 461 | } 462 | 463 | // int i; 464 | // for (i = 0; i < tf_num_values; i++) { 465 | // php_printf("dtypes[%d] ? %d\n", i, tf_values[i]); 466 | // } 467 | // php_printf("tf_num_values ? %d\n", tf_num_values); 468 | 469 | // this 470 | t_tf_operation_description_object* intern = TF_OPERATION_DESCRIPTION_P_ZV(getThis()); 471 | t_tf_operation_description* node = intern->ptr; 472 | 473 | TF_SetAttrTypeList(node->src, name->val, tf_values, tf_num_values); 474 | } 475 | 476 | --------------------------------------------------------------------------------