@@ -15,58 +15,116 @@ limitations under the License.
1515******************************************************************************/
1616
1717using System ;
18+ using System . Runtime . CompilerServices ;
1819using System . Runtime . InteropServices ;
20+ using NumSharp . Backends . Unmanaged ;
21+ using static Tensorflow . c_api ;
1922
2023namespace Tensorflow
2124{
25+ /// <summary>
26+ /// Represents a TF_Buffer that can be passed to Tensorflow.
27+ /// </summary>
2228 public class Buffer : DisposableObject
2329 {
24- private TF_Buffer buffer => Marshal . PtrToStructure < TF_Buffer > ( _handle ) ;
30+ private unsafe TF_Buffer buffer
31+ {
32+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
33+ get => * bufferptr ;
34+ }
35+
36+ private unsafe TF_Buffer * bufferptr
37+ {
38+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
39+ get => ( TF_Buffer * ) _handle ;
40+ }
2541
26- public byte [ ] Data
42+ /// <summary>
43+ /// The memory block representing this buffer.
44+ /// </summary>
45+ /// <remarks>The deallocator is set to null.</remarks>
46+ public UnmanagedMemoryBlock < byte > MemoryBlock
2747 {
28- get
48+ get
2949 {
30- var data = new byte [ buffer . length ] ;
31- if ( data . Length > 0 )
32- Marshal . Copy ( buffer . data , data , 0 , data . Length ) ;
33- return data ;
50+ unsafe
51+ {
52+ EnsureNotDisposed ( ) ;
53+ var buff = ( TF_Buffer * ) _handle ;
54+ return new UnmanagedMemoryBlock < byte > ( ( byte * ) buff ->data . ToPointer ( ) , ( long ) buff ->length ) ;
55+ }
3456 }
3557 }
3658
37- public int Length => ( int ) buffer . length ;
38-
39- public Buffer ( )
59+ /// <summary>
60+ /// The bytes length of this buffer.
61+ /// </summary>
62+ public ulong Length
4063 {
41- _handle = c_api . TF_NewBuffer ( ) ;
64+ get
65+ {
66+ EnsureNotDisposed ( ) ;
67+ return buffer . length ;
68+ }
4269 }
4370
44- public Buffer ( IntPtr handle )
71+ public Buffer ( ) => _handle = TF_NewBuffer ( ) ;
72+
73+ internal Buffer ( IntPtr handle )
4574 {
75+ if ( handle == IntPtr . Zero )
76+ throw new ArgumentException ( "Handle (IntPtr) can't be zero." , nameof ( handle ) ) ;
77+
4678 _handle = handle ;
4779 }
4880
49- public Buffer ( byte [ ] data )
50- {
51- var dst = Marshal . AllocHGlobal ( data . Length ) ;
52- Marshal . Copy ( data , 0 , dst , data . Length ) ;
81+ public Buffer ( byte [ ] data ) : this ( _toBuffer ( data ) )
82+ { }
5383
54- _handle = c_api . TF_NewBufferFromString ( dst , ( ulong ) data . Length ) ;
84+ private static IntPtr _toBuffer ( byte [ ] data )
85+ {
86+ if ( data == null )
87+ throw new ArgumentNullException ( nameof ( data ) ) ;
5588
56- Marshal . FreeHGlobal ( dst ) ;
89+ unsafe
90+ {
91+ fixed ( byte * src = data )
92+ return TF_NewBufferFromString ( new IntPtr ( src ) , ( ulong ) data . LongLength ) ;
93+ }
5794 }
5895
5996 public static implicit operator IntPtr ( Buffer buffer )
6097 {
98+ buffer . EnsureNotDisposed ( ) ;
6199 return buffer . _handle ;
62100 }
63101
64- public static implicit operator byte [ ] ( Buffer buffer )
102+ public static explicit operator byte [ ] ( Buffer buffer ) => buffer . ToArray ( ) ; //has to be explicit, developer will assume it doesn't cost.
103+
104+ /// <summary>
105+ /// Copies this buffer's contents onto a <see cref="byte"/> array.
106+ /// </summary>
107+ public byte [ ] ToArray ( )
65108 {
66- return buffer . Data ;
109+ EnsureNotDisposed ( ) ;
110+
111+ unsafe
112+ {
113+ var len = buffer . length ;
114+ if ( len == 0 )
115+ return Array . Empty < byte > ( ) ;
116+
117+ byte [ ] data = new byte [ len ] ;
118+ fixed ( byte * dst = data )
119+ System . Buffer . MemoryCopy ( ( void * ) bufferptr ->data , dst , len , len ) ;
120+
121+ return data ;
122+ }
67123 }
68124
69125 protected override void DisposeUnmanagedResources ( IntPtr handle )
70- => c_api . TF_DeleteBuffer ( handle ) ;
126+ {
127+ TF_DeleteBuffer ( handle ) ;
128+ }
71129 }
72- }
130+ }
0 commit comments