From 9437b7277c12b9956459975462e2c26559e538dc Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Thu, 3 Jan 2019 10:50:32 -0600 Subject: [PATCH] CApiAttributesTest.String, TF_SetAttrString, TF_OperationGetAttrString --- .../Operations/TF_AttrMetadata.cs | 14 +++ .../Operations/TF_AttrType.cs | 19 +++++ .../Operations/c_api.ops.cs | 41 +++++++++ .../CApiAttributesTestcs.cs | 85 +++++++++++++++++++ test/TensorFlowNET.UnitTest/c_test_util.cs | 19 ----- 5 files changed, 159 insertions(+), 19 deletions(-) create mode 100644 src/TensorFlowNET.Core/Operations/TF_AttrMetadata.cs create mode 100644 src/TensorFlowNET.Core/Operations/TF_AttrType.cs create mode 100644 test/TensorFlowNET.UnitTest/CApiAttributesTestcs.cs diff --git a/src/TensorFlowNET.Core/Operations/TF_AttrMetadata.cs b/src/TensorFlowNET.Core/Operations/TF_AttrMetadata.cs new file mode 100644 index 00000000..41ae6a3b --- /dev/null +++ b/src/TensorFlowNET.Core/Operations/TF_AttrMetadata.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow +{ + public struct TF_AttrMetadata + { + public char is_list; + public long list_size; + public TF_AttrType type; + public long total_size; + } +} diff --git a/src/TensorFlowNET.Core/Operations/TF_AttrType.cs b/src/TensorFlowNET.Core/Operations/TF_AttrType.cs new file mode 100644 index 00000000..8a0dc1dc --- /dev/null +++ b/src/TensorFlowNET.Core/Operations/TF_AttrType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow +{ + public enum TF_AttrType + { + TF_ATTR_STRING = 0, + TF_ATTR_INT = 1, + TF_ATTR_FLOAT = 2, + TF_ATTR_BOOL = 3, + TF_ATTR_TYPE = 4, + TF_ATTR_SHAPE = 5, + TF_ATTR_TENSOR = 6, + TF_ATTR_PLACEHOLDER = 7, + TF_ATTR_FUNC = 8 + } +} diff --git a/src/TensorFlowNET.Core/Operations/c_api.ops.cs b/src/TensorFlowNET.Core/Operations/c_api.ops.cs index 0fb55730..b330944f 100644 --- a/src/TensorFlowNET.Core/Operations/c_api.ops.cs +++ b/src/TensorFlowNET.Core/Operations/c_api.ops.cs @@ -40,6 +40,33 @@ namespace Tensorflow [DllImport(TensorFlowLibName)] public static extern IntPtr TF_OperationDevice(IntPtr oper); + /// + /// Fills in `value` with the value of the attribute `attr_name`. `value` must + /// point to an array of length at least `max_length` (ideally set to + /// TF_AttrMetadata.total_size from TF_OperationGetAttrMetadata(oper, + /// attr_name)). + /// + /// TF_Operation* + /// const char* + /// TF_Status* + /// + [DllImport(TensorFlowLibName)] + public static extern TF_AttrMetadata TF_OperationGetAttrMetadata(IntPtr oper, string attr_name, IntPtr status); + + /// + /// Fills in `value` with the value of the attribute `attr_name`. `value` must + /// point to an array of length at least `max_length` (ideally set to + /// TF_AttrMetadata.total_size from TF_OperationGetAttrMetadata(oper, + /// attr_name)). + /// + /// TF_Operation* + /// const char* + /// void* + /// size_t + /// TF_Status* + [DllImport(TensorFlowLibName)] + public static extern void TF_OperationGetAttrString(IntPtr oper, string attr_name, IntPtr value, uint max_length, IntPtr status); + /// /// Sets `output_attr_value` to the binary-serialized AttrValue proto /// representation of the value of the `attr_name` attr of `oper`. @@ -170,6 +197,20 @@ namespace Tensorflow [DllImport(TensorFlowLibName)] public static extern void TF_SetAttrShape(IntPtr desc, string attr_name, long[] dims, int num_dims); + /// + /// Call some TF_SetAttr*() function for every attr that is not + /// inferred from an input and doesn't have a default value you wish to + /// keep. + /// + /// `value` must point to a string of length `length` bytes. + /// + /// TF_OperationDescription* + /// const char* + /// const void* + /// size_t + [DllImport(TensorFlowLibName)] + public static extern void TF_SetAttrString(IntPtr desc, string attr_name, string value, uint length); + [DllImport(TensorFlowLibName)] public static extern void TF_SetAttrTensor(IntPtr desc, string attr_name, IntPtr value, IntPtr status); diff --git a/test/TensorFlowNET.UnitTest/CApiAttributesTestcs.cs b/test/TensorFlowNET.UnitTest/CApiAttributesTestcs.cs new file mode 100644 index 00000000..2e4d2d1a --- /dev/null +++ b/test/TensorFlowNET.UnitTest/CApiAttributesTestcs.cs @@ -0,0 +1,85 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Text; +using Tensorflow; + +namespace TensorFlowNET.UnitTest +{ + /// + /// tensorflow\c\c_api_test.cc + /// `class CApiAttributesTest` + /// + [TestClass] + public class CApiAttributesTestcs : CApiTest, IDisposable + { + private Graph graph_; + private int counter_; + private Status s_; + + public CApiAttributesTestcs() + { + s_ = new Status(); + graph_ = new Graph(); + } + + private OperationDescription init(string type) + { + // Construct op_name to match the name used by REGISTER_OP in the + // ATTR_TEST_REGISTER calls above. + string op_name = "CApiAttributesTestOp"; + if (type.Contains("list(")) + { + op_name += "List"; + type = type.Substring(5, type.Length - 6); + } + op_name += type; + return c_api.TF_NewOperation(graph_, op_name, $"name{counter_++}"); + } + + /// + /// REGISTER_OP for CApiAttributesTest test cases. + /// Registers two ops, each with a single attribute called 'v'. + /// The attribute in one op will have a type 'type', the other + /// will have list(type). + /// + /// + private void ATTR_TEST_REGISTER_OP(string type) + { + + } + + private void EXPECT_TF_META(Operation oper, string attr_name, int expected_list_size, TF_AttrType expected_type, uint expected_total_size) + { + var m = c_api.TF_OperationGetAttrMetadata(oper, attr_name, s_); + EXPECT_EQ(TF_Code.TF_OK, s_.Code); + char e = expected_list_size >= 0 ? (char)1 : (char)0; + EXPECT_EQ(e, m.is_list); + EXPECT_EQ(expected_list_size, m.list_size); + EXPECT_EQ(expected_type, m.type); + EXPECT_EQ(expected_total_size, m.total_size); + } + + [TestMethod] + public void String() + { + //var desc = init("string"); + //c_api.TF_SetAttrString(desc, "v", "bunny", 5); + + //var oper = c_api.TF_FinishOperation(desc, s_); + //ASSERT_EQ(TF_Code.TF_OK, s_.Code); + //EXPECT_TF_META(oper, "v", -1, TF_AttrType.TF_ATTR_STRING, 5); + //var value = new char[5]; + + //c_api.TF_OperationGetAttrString(oper, "v", value, 5, s_); + //EXPECT_EQ(TF_Code.TF_OK, s_.Code); + //EXPECT_EQ("bunny", value, 5)); + } + + public void Dispose() + { + graph_.Dispose(); + s_.Dispose(); + } + } +} diff --git a/test/TensorFlowNET.UnitTest/c_test_util.cs b/test/TensorFlowNET.UnitTest/c_test_util.cs index 2ed657f8..07d760c9 100644 --- a/test/TensorFlowNET.UnitTest/c_test_util.cs +++ b/test/TensorFlowNET.UnitTest/c_test_util.cs @@ -176,11 +176,6 @@ namespace TensorFlowNET.UnitTest } public static Operation Neg(Operation n, Graph graph, Status s, string name = "neg") - { - return NegHelper(n, graph, s, name); - } - - public static Operation NegHelper(Operation n, Graph graph, Status s, string name) { OperationDescription desc = c_api.TF_NewOperation(graph, "Neg", name); var neg_input = new TF_Output(n, 0); @@ -221,19 +216,5 @@ namespace TensorFlowNET.UnitTest { return Const(new Tensor(v), graph, s, name); } - - public static unsafe IntPtr Int32Tensor(int v) - { - bool deallocator_called = false; - const int num_bytes = sizeof(int); - var dotHandle = Marshal.AllocHGlobal(num_bytes * 1); - *(int*)dotHandle = v; - return c_api.TF_NewTensor(TF_DataType.TF_INT32, new long[0], 0, dotHandle, num_bytes, - (IntPtr values, IntPtr len, ref bool closure) => - { - // Free the original buffer and set flag - // Marshal.FreeHGlobal(dotHandle); - }, ref deallocator_called); - } } }