public static void MXNDListGet(NDListHandle handle,
                                       uint index,
                                       out string out_key,
                                       out float[] out_data,
                                       out uint[] out_shape,
                                       out uint out_ndim)
        {
            var ret = NativeMethods.MXNDListGet(handle.NativePtr, index, out var out_key_ptr, out var out_data_ptr, out var out_shape_ptr, out out_ndim);

            if (ret != NativeMethods.OK)
            {
                throw CreateMXNetException($"Failed to get list from {nameof(NDListHandle)}");
            }

            out_shape = new uint[out_ndim];
            NativeMethods.memcpy(out_shape, out_shape_ptr, out_ndim * sizeof(uint));

            var size = 1u;

            for (var i = 0u; i < out_ndim; ++i)
            {
                size *= out_shape[i];
            }

            out_data = new float[size];
            NativeMethods.memcpy(out_data, out_data_ptr, size * sizeof(float));

            out_key = Marshal.PtrToStringAnsi(out_key_ptr);
        }
        public static void MXNDListCreate(byte[] nd_file_bytes,
                                          int nd_file_size,
                                          out NDListHandle handle,
                                          out uint out_length)
        {
            var ret = NativeMethods.MXNDListCreate(nd_file_bytes, nd_file_size, out var @out, out out_length);

            if (ret != NativeMethods.OK)
            {
                throw CreateMXNetException($"Failed to create {nameof(PredictorHandle)}");
            }

            handle = new NDListHandle(@out);
        }