From caae2dbd66d5a6a4d76d849182bf2db363e5595e Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 4 Feb 2020 19:10:18 -0800 Subject: [PATCH] Implement SafeBufferHandle as a wrapper for TF_Buffer --- .../Attributes/c_api.ops.cs | 2 +- src/TensorFlowNET.Core/Buffers/Buffer.cs | 88 ++++++++----------- .../Buffers/SafeBufferHandle.cs | 40 +++++++++ .../Buffers/c_api.buffer.cs | 4 +- src/TensorFlowNET.Core/Framework/importer.cs | 2 +- .../Framework/op_def_registry.py.cs | 2 +- .../GraphTransformation/GraphTransformer.cs | 2 +- .../c_api.transform_graph.cs | 2 +- src/TensorFlowNET.Core/Graphs/Graph.Export.cs | 4 +- src/TensorFlowNET.Core/Graphs/Graph.Import.cs | 4 +- src/TensorFlowNET.Core/Graphs/c_api.graph.cs | 10 +-- .../Operations/Operation.cs | 8 +- .../Operations/c_api.ops.cs | 4 +- .../Util/SafeHandleLease.cs | 10 +++ test/TensorFlowNET.UnitTest/GraphTest.cs | 12 +-- .../NativeAPI/CApiGradientsTest.cs | 4 +- .../NativeAPI/c_test_util.cs | 8 +- test/TensorFlowNET.UnitTest/OperationsTest.cs | 4 +- 18 files changed, 121 insertions(+), 89 deletions(-) create mode 100644 src/TensorFlowNET.Core/Buffers/SafeBufferHandle.cs diff --git a/src/TensorFlowNET.Core/Attributes/c_api.ops.cs b/src/TensorFlowNET.Core/Attributes/c_api.ops.cs index 0bca1bba..8480e92a 100644 --- a/src/TensorFlowNET.Core/Attributes/c_api.ops.cs +++ b/src/TensorFlowNET.Core/Attributes/c_api.ops.cs @@ -55,7 +55,7 @@ namespace Tensorflow /// /// [DllImport(TensorFlowLibName)] - public static extern int TF_OperationGetAttrValueProto(IntPtr oper, string attr_name, IntPtr output_attr_value, SafeStatusHandle status); + public static extern int TF_OperationGetAttrValueProto(IntPtr oper, string attr_name, SafeBufferHandle output_attr_value, SafeStatusHandle status); [DllImport(TensorFlowLibName)] public static extern void TF_SetAttrBool(IntPtr desc, string attr_name, bool value); diff --git a/src/TensorFlowNET.Core/Buffers/Buffer.cs b/src/TensorFlowNET.Core/Buffers/Buffer.cs index ad5dbc44..d810dbf2 100644 --- a/src/TensorFlowNET.Core/Buffers/Buffer.cs +++ b/src/TensorFlowNET.Core/Buffers/Buffer.cs @@ -14,10 +14,11 @@ limitations under the License. ******************************************************************************/ +using NumSharp.Backends.Unmanaged; using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using NumSharp.Backends.Unmanaged; +using Tensorflow.Util; using static Tensorflow.c_api; namespace Tensorflow @@ -25,34 +26,30 @@ namespace Tensorflow /// /// Represents a TF_Buffer that can be passed to Tensorflow. /// - public class Buffer : DisposableObject + public sealed class Buffer : IDisposable { - private unsafe TF_Buffer buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => *bufferptr; - } + public SafeBufferHandle Handle { get; } - private unsafe TF_Buffer* bufferptr - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (TF_Buffer*) _handle; - } + /// + /// + /// + private unsafe ref readonly TF_Buffer DangerousBuffer + => ref Unsafe.AsRef(Handle.DangerousGetHandle().ToPointer()); /// /// The memory block representing this buffer. /// - /// The deallocator is set to null. - public UnmanagedMemoryBlock MemoryBlock + /// + /// The deallocator is set to null. + /// + /// + /// + public unsafe UnmanagedMemoryBlock DangerousMemoryBlock { get { - unsafe - { - EnsureNotDisposed(); - var buff = (TF_Buffer*) _handle; - return new UnmanagedMemoryBlock((byte*) buff->data.ToPointer(), (long) buff->length); - } + ref readonly TF_Buffer buffer = ref DangerousBuffer; + return new UnmanagedMemoryBlock((byte*)buffer.data.ToPointer(), (long)buffer.length); } } @@ -63,25 +60,23 @@ namespace Tensorflow { get { - EnsureNotDisposed(); - return buffer.length; + using (Handle.Lease()) + { + return DangerousBuffer.length; + } } } - public Buffer() => _handle = TF_NewBuffer(); - - public Buffer(IntPtr handle) - { - if (handle == IntPtr.Zero) - throw new ArgumentException("Handle (IntPtr) can't be zero.", nameof(handle)); + public Buffer() + => Handle = TF_NewBuffer(); - _handle = handle; - } + public Buffer(SafeBufferHandle handle) + => Handle = handle; - public Buffer(byte[] data) : this(_toBuffer(data)) - { } + public Buffer(byte[] data) + => Handle = _toBuffer(data); - private static IntPtr _toBuffer(byte[] data) + private static SafeBufferHandle _toBuffer(byte[] data) { if (data == null) throw new ArgumentNullException(nameof(data)); @@ -93,38 +88,25 @@ namespace Tensorflow } } - public static implicit operator IntPtr(Buffer buffer) - { - buffer.EnsureNotDisposed(); - return buffer._handle; - } - - public static explicit operator byte[](Buffer buffer) => buffer.ToArray(); //has to be explicit, developer will assume it doesn't cost. - /// /// Copies this buffer's contents onto a array. /// public byte[] ToArray() { - EnsureNotDisposed(); - - unsafe + using (Handle.Lease()) { - var len = buffer.length; + var block = DangerousMemoryBlock; + var len = block.Count; if (len == 0) return Array.Empty(); - byte[] data = new byte[len]; - fixed (byte* dst = data) - System.Buffer.MemoryCopy((void*) bufferptr->data, dst, len, len); - + var data = new byte[len]; + block.CopyTo(data, 0); return data; } } - protected override void DisposeUnmanagedResources(IntPtr handle) - { - TF_DeleteBuffer(handle); - } + public void Dispose() + => Handle.Dispose(); } } \ No newline at end of file diff --git a/src/TensorFlowNET.Core/Buffers/SafeBufferHandle.cs b/src/TensorFlowNET.Core/Buffers/SafeBufferHandle.cs new file mode 100644 index 00000000..82678d54 --- /dev/null +++ b/src/TensorFlowNET.Core/Buffers/SafeBufferHandle.cs @@ -0,0 +1,40 @@ +/***************************************************************************** + Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +******************************************************************************/ + +using System; +using Tensorflow.Util; + +namespace Tensorflow +{ + public sealed class SafeBufferHandle : SafeTensorflowHandle + { + private SafeBufferHandle() + { + } + + public SafeBufferHandle(IntPtr handle) + : base(handle) + { + } + + protected override bool ReleaseHandle() + { + c_api.TF_DeleteBuffer(handle); + SetHandle(IntPtr.Zero); + return true; + } + } +} diff --git a/src/TensorFlowNET.Core/Buffers/c_api.buffer.cs b/src/TensorFlowNET.Core/Buffers/c_api.buffer.cs index 45d165d5..a7dc0ff2 100644 --- a/src/TensorFlowNET.Core/Buffers/c_api.buffer.cs +++ b/src/TensorFlowNET.Core/Buffers/c_api.buffer.cs @@ -29,7 +29,7 @@ namespace Tensorflow /// /// [DllImport(TensorFlowLibName)] - public static extern IntPtr TF_NewBuffer(); + public static extern SafeBufferHandle TF_NewBuffer(); [DllImport(TensorFlowLibName)] public static extern IntPtr TF_GetBuffer(TF_Buffer buffer); @@ -42,6 +42,6 @@ namespace Tensorflow /// size_t /// [DllImport(TensorFlowLibName)] - public static extern IntPtr TF_NewBufferFromString(IntPtr proto, ulong proto_len); + public static extern SafeBufferHandle TF_NewBufferFromString(IntPtr proto, ulong proto_len); } } diff --git a/src/TensorFlowNET.Core/Framework/importer.cs b/src/TensorFlowNET.Core/Framework/importer.cs index 4a35f8d8..8dd30858 100644 --- a/src/TensorFlowNET.Core/Framework/importer.cs +++ b/src/TensorFlowNET.Core/Framework/importer.cs @@ -62,7 +62,7 @@ namespace Tensorflow { _PopulateTFImportGraphDefOptions(scoped_options, prefix, input_map, return_elements); // need to create a class ImportGraphDefWithResults with IDisposal - results = c_api.TF_GraphImportGraphDefWithResults(graph, buffer, scoped_options.Handle, status.Handle); + results = c_api.TF_GraphImportGraphDefWithResults(graph, buffer.Handle, scoped_options.Handle, status.Handle); status.Check(true); } diff --git a/src/TensorFlowNET.Core/Framework/op_def_registry.py.cs b/src/TensorFlowNET.Core/Framework/op_def_registry.py.cs index 953b5552..e82805e8 100644 --- a/src/TensorFlowNET.Core/Framework/op_def_registry.py.cs +++ b/src/TensorFlowNET.Core/Framework/op_def_registry.py.cs @@ -30,7 +30,7 @@ namespace Tensorflow { _registered_ops = new Dictionary(); using var buffer = new Buffer(c_api.TF_GetAllOpList()); - using var stream = buffer.MemoryBlock.Stream(); + using var stream = buffer.DangerousMemoryBlock.Stream(); var op_list = OpList.Parser.ParseFrom(stream); foreach (var op_def in op_list.Op) _registered_ops[op_def.Name] = op_def; diff --git a/src/TensorFlowNET.Core/GraphTransformation/GraphTransformer.cs b/src/TensorFlowNET.Core/GraphTransformation/GraphTransformer.cs index e1225e63..12f169b0 100644 --- a/src/TensorFlowNET.Core/GraphTransformation/GraphTransformer.cs +++ b/src/TensorFlowNET.Core/GraphTransformation/GraphTransformer.cs @@ -34,7 +34,7 @@ namespace Tensorflow inputs_string, outputs_string, transforms_string, - buffer, + buffer.Handle, status.Handle); status.Check(false); diff --git a/src/TensorFlowNET.Core/GraphTransformation/c_api.transform_graph.cs b/src/TensorFlowNET.Core/GraphTransformation/c_api.transform_graph.cs index a08db0a8..cf62c5fb 100644 --- a/src/TensorFlowNET.Core/GraphTransformation/c_api.transform_graph.cs +++ b/src/TensorFlowNET.Core/GraphTransformation/c_api.transform_graph.cs @@ -27,7 +27,7 @@ namespace Tensorflow string inputs_string, string outputs_string, string transforms_string, - IntPtr output_buffer, + SafeBufferHandle output_buffer, SafeStatusHandle status); } } diff --git a/src/TensorFlowNET.Core/Graphs/Graph.Export.cs b/src/TensorFlowNET.Core/Graphs/Graph.Export.cs index e85cc7be..1d9f7e02 100644 --- a/src/TensorFlowNET.Core/Graphs/Graph.Export.cs +++ b/src/TensorFlowNET.Core/Graphs/Graph.Export.cs @@ -25,7 +25,7 @@ namespace Tensorflow public Buffer ToGraphDef(Status s) { var buffer = new Buffer(); - c_api.TF_GraphToGraphDef(_handle, buffer, s.Handle); + c_api.TF_GraphToGraphDef(_handle, buffer.Handle, s.Handle); s.Check(true); return buffer; @@ -39,7 +39,7 @@ namespace Tensorflow { status.Check(true); // limit size to 250M, recursion to max 100 - var inputStream = CodedInputStream.CreateWithLimits(buffer.MemoryBlock.Stream(), 250 * 1024 * 1024, 100); + var inputStream = CodedInputStream.CreateWithLimits(buffer.DangerousMemoryBlock.Stream(), 250 * 1024 * 1024, 100); def = GraphDef.Parser.ParseFrom(inputStream); } diff --git a/src/TensorFlowNET.Core/Graphs/Graph.Import.cs b/src/TensorFlowNET.Core/Graphs/Graph.Import.cs index 3a919145..298862ff 100644 --- a/src/TensorFlowNET.Core/Graphs/Graph.Import.cs +++ b/src/TensorFlowNET.Core/Graphs/Graph.Import.cs @@ -29,7 +29,7 @@ namespace Tensorflow int size = Marshal.SizeOf(); var return_output_handle = Marshal.AllocHGlobal(size * num_return_outputs); - c_api.TF_GraphImportGraphDefWithReturnOutputs(_handle, graph_def, opts.Handle, return_output_handle, num_return_outputs, s.Handle); + c_api.TF_GraphImportGraphDefWithReturnOutputs(_handle, graph_def.Handle, opts.Handle, return_output_handle, num_return_outputs, s.Handle); var tf_output_ptr = (TF_Output*) return_output_handle; for (int i = 0; i < num_return_outputs; i++) @@ -54,7 +54,7 @@ namespace Tensorflow { as_default(); c_api.TF_ImportGraphDefOptionsSetPrefix(opts.Handle, prefix); - c_api.TF_GraphImportGraphDef(_handle, graph_def, opts.Handle, status.Handle); + c_api.TF_GraphImportGraphDef(_handle, graph_def.Handle, opts.Handle, status.Handle); status.Check(true); return status.Code == TF_Code.TF_OK; } diff --git a/src/TensorFlowNET.Core/Graphs/c_api.graph.cs b/src/TensorFlowNET.Core/Graphs/c_api.graph.cs index 4547d92d..94d6d63e 100644 --- a/src/TensorFlowNET.Core/Graphs/c_api.graph.cs +++ b/src/TensorFlowNET.Core/Graphs/c_api.graph.cs @@ -47,7 +47,7 @@ namespace Tensorflow public static extern string TF_GraphDebugString(IntPtr graph, out int len); [DllImport(TensorFlowLibName)] - public static extern void TF_GraphGetOpDef(IntPtr graph, string op_name, IntPtr output_op_def, SafeStatusHandle status); + public static extern void TF_GraphGetOpDef(IntPtr graph, string op_name, SafeBufferHandle output_op_def, SafeStatusHandle status); /// /// Returns the shape of the Tensor referenced by `output` in `graph` @@ -78,7 +78,7 @@ namespace Tensorflow /// int /// TF_Status* [DllImport(TensorFlowLibName)] - public static extern unsafe void TF_GraphImportGraphDefWithReturnOutputs(IntPtr graph, IntPtr graph_def, SafeImportGraphDefOptionsHandle options, IntPtr return_outputs, int num_return_outputs, SafeStatusHandle status); + public static extern unsafe void TF_GraphImportGraphDefWithReturnOutputs(IntPtr graph, SafeBufferHandle graph_def, SafeImportGraphDefOptionsHandle options, IntPtr return_outputs, int num_return_outputs, SafeStatusHandle status); /// /// Import the graph serialized in `graph_def` into `graph`. Returns nullptr and @@ -92,7 +92,7 @@ namespace Tensorflow /// TF_Status* /// TF_ImportGraphDefResults* [DllImport(TensorFlowLibName)] - public static extern IntPtr TF_GraphImportGraphDefWithResults(IntPtr graph, IntPtr graph_def, SafeImportGraphDefOptionsHandle options, SafeStatusHandle status); + public static extern IntPtr TF_GraphImportGraphDefWithResults(IntPtr graph, SafeBufferHandle graph_def, SafeImportGraphDefOptionsHandle options, SafeStatusHandle status); /// /// Import the graph serialized in `graph_def` into `graph`. @@ -102,7 +102,7 @@ namespace Tensorflow /// TF_ImportGraphDefOptions* /// TF_Status* [DllImport(TensorFlowLibName)] - public static extern void TF_GraphImportGraphDef(IntPtr graph, IntPtr graph_def, SafeImportGraphDefOptionsHandle options, SafeStatusHandle status); + public static extern void TF_GraphImportGraphDef(IntPtr graph, SafeBufferHandle graph_def, SafeImportGraphDefOptionsHandle options, SafeStatusHandle status); /// /// Iterate through the operations of a graph. @@ -138,7 +138,7 @@ namespace Tensorflow /// TF_Buffer* /// TF_Status* [DllImport(TensorFlowLibName)] - public static extern void TF_GraphToGraphDef(IntPtr graph, IntPtr output_graph_def, SafeStatusHandle status); + public static extern void TF_GraphToGraphDef(IntPtr graph, SafeBufferHandle output_graph_def, SafeStatusHandle status); /// /// Returns the number of dimensions of the Tensor referenced by `output` diff --git a/src/TensorFlowNET.Core/Operations/Operation.cs b/src/TensorFlowNET.Core/Operations/Operation.cs index 0d416d32..8af7a422 100644 --- a/src/TensorFlowNET.Core/Operations/Operation.cs +++ b/src/TensorFlowNET.Core/Operations/Operation.cs @@ -236,10 +236,10 @@ namespace Tensorflow lock (Locks.ProcessWide) { using var buf = new Buffer(); - c_api.TF_OperationGetAttrValueProto(_handle, name, buf, tf.status.Handle); + c_api.TF_OperationGetAttrValueProto(_handle, name, buf.Handle, tf.status.Handle); tf.status.Check(true); - x = AttrValue.Parser.ParseFrom(buf.MemoryBlock.Stream()); + x = AttrValue.Parser.ParseFrom(buf.DangerousMemoryBlock.Stream()); } string oneof_value = x.ValueCase.ToString(); @@ -269,10 +269,10 @@ namespace Tensorflow using (var s = new Status()) using (var buffer = new Buffer()) { - c_api.TF_OperationToNodeDef(_handle, buffer, s.Handle); + c_api.TF_OperationToNodeDef(_handle, buffer.Handle, s.Handle); s.Check(); - return NodeDef.Parser.ParseFrom(buffer.MemoryBlock.Stream()); + return NodeDef.Parser.ParseFrom(buffer.DangerousMemoryBlock.Stream()); } } diff --git a/src/TensorFlowNET.Core/Operations/c_api.ops.cs b/src/TensorFlowNET.Core/Operations/c_api.ops.cs index 988bb287..0fc92454 100644 --- a/src/TensorFlowNET.Core/Operations/c_api.ops.cs +++ b/src/TensorFlowNET.Core/Operations/c_api.ops.cs @@ -38,7 +38,7 @@ namespace Tensorflow /// /// [DllImport(TensorFlowLibName)] - public static extern IntPtr TF_GetAllOpList(); + public static extern SafeBufferHandle TF_GetAllOpList(); /// /// For inputs that take a single tensor. @@ -204,7 +204,7 @@ namespace Tensorflow public static extern TF_DataType TF_OperationOutputType(TF_Output oper_out); [DllImport(TensorFlowLibName)] - public static extern void TF_OperationToNodeDef(IntPtr oper, IntPtr buffer, SafeStatusHandle status); + public static extern void TF_OperationToNodeDef(IntPtr oper, SafeBufferHandle buffer, SafeStatusHandle status); [DllImport(TensorFlowLibName)] public static extern int TF_OperationOutputListLength(IntPtr oper, string arg_name, SafeStatusHandle status); diff --git a/src/TensorFlowNET.Core/Util/SafeHandleLease.cs b/src/TensorFlowNET.Core/Util/SafeHandleLease.cs index dcc0e846..19f4ec57 100644 --- a/src/TensorFlowNET.Core/Util/SafeHandleLease.cs +++ b/src/TensorFlowNET.Core/Util/SafeHandleLease.cs @@ -23,6 +23,16 @@ namespace Tensorflow.Util /// Represents a lease of a . /// /// + /// + /// Elements in this section may be referenced by <inheritdoc> elements to provide common + /// language in documentation remarks. + /// + /// + /// The result of this method is only valid when the underlying handle has not been disposed. If the lifetime + /// of the object is unclear, a lease may be used to prevent disposal while the object is in use. See + /// . + /// + /// public readonly struct SafeHandleLease : IDisposable { private readonly SafeHandle _handle; diff --git a/test/TensorFlowNET.UnitTest/GraphTest.cs b/test/TensorFlowNET.UnitTest/GraphTest.cs index e2855425..868fd1b8 100644 --- a/test/TensorFlowNET.UnitTest/GraphTest.cs +++ b/test/TensorFlowNET.UnitTest/GraphTest.cs @@ -216,7 +216,7 @@ namespace TensorFlowNET.UnitTest.NativeAPI // Export to a GraphDef. var graph_def = new Buffer(); - c_api.TF_GraphToGraphDef(graph, graph_def, s.Handle); + c_api.TF_GraphToGraphDef(graph, graph_def.Handle, s.Handle); EXPECT_EQ(TF_Code.TF_OK, s.Code); // Import it, with a prefix, in a fresh graph. @@ -225,7 +225,7 @@ namespace TensorFlowNET.UnitTest.NativeAPI using (var opts = c_api.TF_NewImportGraphDefOptions()) { c_api.TF_ImportGraphDefOptionsSetPrefix(opts, "imported"); - c_api.TF_GraphImportGraphDef(graph, graph_def, opts, s.Handle); + c_api.TF_GraphImportGraphDef(graph, graph_def.Handle, opts, s.Handle); EXPECT_EQ(TF_Code.TF_OK, s.Code); } @@ -270,7 +270,7 @@ namespace TensorFlowNET.UnitTest.NativeAPI EXPECT_EQ(2, c_api.TF_ImportGraphDefOptionsNumReturnOutputs(opts)); c_api.TF_ImportGraphDefOptionsAddReturnOperation(opts, "scalar"); EXPECT_EQ(1, c_api.TF_ImportGraphDefOptionsNumReturnOperations(opts)); - results = c_api.TF_GraphImportGraphDefWithResults(graph, graph_def, opts, s.Handle); + results = c_api.TF_GraphImportGraphDefWithResults(graph, graph_def.Handle, opts, s.Handle); EXPECT_EQ(TF_Code.TF_OK, s.Code); } @@ -303,7 +303,7 @@ namespace TensorFlowNET.UnitTest.NativeAPI c_api.TF_ImportGraphDefOptionsSetPrefix(opts, "imported3"); c_api.TF_ImportGraphDefOptionsAddControlDependency(opts, feed); c_api.TF_ImportGraphDefOptionsAddControlDependency(opts, feed2); - c_api.TF_GraphImportGraphDef(graph, graph_def, opts, s.Handle); + c_api.TF_GraphImportGraphDef(graph, graph_def.Handle, opts, s.Handle); EXPECT_EQ(TF_Code.TF_OK, s.Code); } @@ -328,7 +328,7 @@ namespace TensorFlowNET.UnitTest.NativeAPI // Export to a graph def so we can import a graph with control dependencies graph_def = new Buffer(); - c_api.TF_GraphToGraphDef(graph, graph_def, s.Handle); + c_api.TF_GraphToGraphDef(graph, graph_def.Handle, s.Handle); EXPECT_EQ(TF_Code.TF_OK, s.Code); // Import again, with remapped control dependency, into the same graph @@ -336,7 +336,7 @@ namespace TensorFlowNET.UnitTest.NativeAPI { c_api.TF_ImportGraphDefOptionsSetPrefix(opts, "imported4"); c_api.TF_ImportGraphDefOptionsRemapControlDependency(opts, "imported/feed", feed); - c_api.TF_GraphImportGraphDef(graph, graph_def, opts, s.Handle); + c_api.TF_GraphImportGraphDef(graph, graph_def.Handle, opts, s.Handle); ASSERT_EQ(TF_Code.TF_OK, s.Code); } diff --git a/test/TensorFlowNET.UnitTest/NativeAPI/CApiGradientsTest.cs b/test/TensorFlowNET.UnitTest/NativeAPI/CApiGradientsTest.cs index e9d2012b..597b08ed 100644 --- a/test/TensorFlowNET.UnitTest/NativeAPI/CApiGradientsTest.cs +++ b/test/TensorFlowNET.UnitTest/NativeAPI/CApiGradientsTest.cs @@ -50,11 +50,11 @@ namespace TensorFlowNET.UnitTest.NativeAPI { using (var buffer = new Buffer()) { - c_api.TF_GraphToGraphDef(graph, buffer, s.Handle); + c_api.TF_GraphToGraphDef(graph, buffer.Handle, s.Handle); bool ret = TF_GetCode(s) == TF_OK; EXPECT_EQ(TF_OK, TF_GetCode(s)); if (ret) - graph_def = GraphDef.Parser.ParseFrom(buffer.MemoryBlock.Stream()); + graph_def = GraphDef.Parser.ParseFrom(buffer.DangerousMemoryBlock.Stream()); return ret; } } diff --git a/test/TensorFlowNET.UnitTest/NativeAPI/c_test_util.cs b/test/TensorFlowNET.UnitTest/NativeAPI/c_test_util.cs index 48c717c8..cd62c5ac 100644 --- a/test/TensorFlowNET.UnitTest/NativeAPI/c_test_util.cs +++ b/test/TensorFlowNET.UnitTest/NativeAPI/c_test_util.cs @@ -38,8 +38,8 @@ namespace TensorFlowNET.UnitTest { using (var buffer = new Buffer()) { - c_api.TF_OperationGetAttrValueProto(oper, attr_name, buffer, s.Handle); - attr_value = AttrValue.Parser.ParseFrom(buffer.MemoryBlock.Stream()); + c_api.TF_OperationGetAttrValueProto(oper, attr_name, buffer.Handle, s.Handle); + attr_value = AttrValue.Parser.ParseFrom(buffer.DangerousMemoryBlock.Stream()); } return s.Code == TF_Code.TF_OK; @@ -53,9 +53,9 @@ namespace TensorFlowNET.UnitTest using (var s = new Status()) using (var buffer = new Buffer()) { - c_api.TF_GraphToGraphDef(graph, buffer, s.Handle); + c_api.TF_GraphToGraphDef(graph, buffer.Handle, s.Handle); s.Check(); - return GraphDef.Parser.ParseFrom(buffer.MemoryBlock.Stream()); + return GraphDef.Parser.ParseFrom(buffer.DangerousMemoryBlock.Stream()); } } } diff --git a/test/TensorFlowNET.UnitTest/OperationsTest.cs b/test/TensorFlowNET.UnitTest/OperationsTest.cs index 5d3e54b5..ba503dca 100644 --- a/test/TensorFlowNET.UnitTest/OperationsTest.cs +++ b/test/TensorFlowNET.UnitTest/OperationsTest.cs @@ -22,8 +22,8 @@ namespace TensorFlowNET.UnitTest.Basics public void GetAllOpList() { var handle = c_api.TF_GetAllOpList(); - var buffer = new Buffer(handle); - var op_list = OpList.Parser.ParseFrom(buffer.MemoryBlock.Stream()); + using var buffer = new Buffer(handle); + var op_list = OpList.Parser.ParseFrom(buffer.DangerousMemoryBlock.Stream()); var _registered_ops = new Dictionary(); foreach (var op_def in op_list.Op)