public static void CleanUpNativeData(ref IntPtr pNativeData)
        {
            if (pNativeData != IntPtr.Zero)
            {
                XSQLDA xsqlda = Marshal.PtrToStructure <XSQLDA>(pNativeData);

                Marshal.DestroyStructure <XSQLDA>(pNativeData);

                for (var i = 0; i < xsqlda.sqln; i++)
                {
                    IntPtr ptr = GetIntPtr(pNativeData, ComputeLength(i));

                    var sqlvar = new XSQLVAR();
                    MarshalXSQLVARNativeToManaged(ptr, sqlvar, true);

                    if (sqlvar.sqldata != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(sqlvar.sqldata);
                        sqlvar.sqldata = IntPtr.Zero;
                    }

                    if (sqlvar.sqlind != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(sqlvar.sqlind);
                        sqlvar.sqlind = IntPtr.Zero;
                    }

                    Marshal.DestroyStructure <XSQLVAR>(ptr);
                }

                Marshal.FreeHGlobal(pNativeData);

                pNativeData = IntPtr.Zero;
            }
        }
        public static IntPtr MarshalManagedToNative(Charset charset, Descriptor descriptor)
        {
            // Set up XSQLDA structure
            var xsqlda = new XSQLDA
            {
                version = descriptor.Version,
                sqln    = descriptor.Count,
                sqld    = descriptor.ActualCount
            };

            var xsqlvar = new XSQLVAR[descriptor.Count];

            for (var i = 0; i < xsqlvar.Length; i++)
            {
                // Create a	new	XSQLVAR	structure and fill it
                xsqlvar[i] = new XSQLVAR
                {
                    sqltype    = descriptor[i].DataType,
                    sqlscale   = descriptor[i].NumericScale,
                    sqlsubtype = descriptor[i].SubType,
                    sqllen     = descriptor[i].Length
                };


                // Create a	new	pointer	for	the	xsqlvar	data
                if (descriptor[i].HasDataType() && descriptor[i].DbDataType != DbDataType.Null)
                {
                    var buffer = descriptor[i].DbValue.GetBytes();
                    xsqlvar[i].sqldata = Marshal.AllocHGlobal(buffer.Length);
                    Marshal.Copy(buffer, 0, xsqlvar[i].sqldata, buffer.Length);
                }
                else
                {
                    xsqlvar[i].sqldata = Marshal.AllocHGlobal(0);
                }

                // Create a	new	pointer	for	the	sqlind value
                xsqlvar[i].sqlind = Marshal.AllocHGlobal(Marshal2.SizeOf <short>());
                Marshal.WriteInt16(xsqlvar[i].sqlind, descriptor[i].NullFlag);

                // Name
                xsqlvar[i].sqlname        = GetStringBuffer(charset, descriptor[i].Name);
                xsqlvar[i].sqlname_length = (short)descriptor[i].Name.Length;

                // Relation	Name
                xsqlvar[i].relname        = GetStringBuffer(charset, descriptor[i].Relation);
                xsqlvar[i].relname_length = (short)descriptor[i].Relation.Length;

                // Owner name
                xsqlvar[i].ownername        = GetStringBuffer(charset, descriptor[i].Owner);
                xsqlvar[i].ownername_length = (short)descriptor[i].Owner.Length;

                // Alias name
                xsqlvar[i].aliasname        = GetStringBuffer(charset, descriptor[i].Alias);
                xsqlvar[i].aliasname_length = (short)descriptor[i].Alias.Length;
            }

            return(MarshalManagedToNative(xsqlda, xsqlvar));
        }
        public static async ValueTask <IntPtr> MarshalManagedToNative(Charset charset, Descriptor descriptor, AsyncWrappingCommonArgs async)
        {
            var xsqlda = new XSQLDA
            {
                version = descriptor.Version,
                sqln    = descriptor.Count,
                sqld    = descriptor.ActualCount
            };

            var xsqlvar = new XSQLVAR[descriptor.Count];

            for (var i = 0; i < xsqlvar.Length; i++)
            {
                xsqlvar[i] = new XSQLVAR
                {
                    sqltype    = descriptor[i].DataType,
                    sqlscale   = descriptor[i].NumericScale,
                    sqlsubtype = descriptor[i].SubType,
                    sqllen     = descriptor[i].Length
                };


                if (descriptor[i].HasDataType() && descriptor[i].DbDataType != DbDataType.Null)
                {
                    var buffer = await descriptor[i].DbValue.GetBytes(async).ConfigureAwait(false);
                    xsqlvar[i].sqldata = Marshal.AllocHGlobal(buffer.Length);
                    Marshal.Copy(buffer, 0, xsqlvar[i].sqldata, buffer.Length);
                }
                else
                {
                    xsqlvar[i].sqldata = Marshal.AllocHGlobal(0);
                }

                xsqlvar[i].sqlind = Marshal.AllocHGlobal(Marshal.SizeOf <short>());
                Marshal.WriteInt16(xsqlvar[i].sqlind, descriptor[i].NullFlag);

                xsqlvar[i].sqlname        = GetStringBuffer(charset, descriptor[i].Name);
                xsqlvar[i].sqlname_length = (short)descriptor[i].Name.Length;

                xsqlvar[i].relname        = GetStringBuffer(charset, descriptor[i].Relation);
                xsqlvar[i].relname_length = (short)descriptor[i].Relation.Length;

                xsqlvar[i].ownername        = GetStringBuffer(charset, descriptor[i].Owner);
                xsqlvar[i].ownername_length = (short)descriptor[i].Owner.Length;

                xsqlvar[i].aliasname        = GetStringBuffer(charset, descriptor[i].Alias);
                xsqlvar[i].aliasname_length = (short)descriptor[i].Alias.Length;
            }

            return(MarshalManagedToNative(xsqlda, xsqlvar));
        }
        public static IntPtr MarshalManagedToNative(XSQLDA xsqlda, XSQLVAR[] xsqlvar)
        {
            var size = ComputeLength(xsqlda.sqln);
            var ptr  = Marshal.AllocHGlobal(size);

            Marshal.StructureToPtr(xsqlda, ptr, true);

            for (var i = 0; i < xsqlvar.Length; i++)
            {
                var offset = ComputeLength(i);
                Marshal.StructureToPtr(xsqlvar[i], GetIntPtr(ptr, offset), true);
            }

            return(ptr);
        }
        public static void CleanUpNativeData(ref IntPtr pNativeData)
        {
            if (pNativeData != IntPtr.Zero)
            {
                // Obtain XSQLDA information
                XSQLDA xsqlda = Marshal2.PtrToStructure <XSQLDA>(pNativeData);

                // Destroy XSQLDA structure
                Marshal2.DestroyStructure <XSQLDA>(pNativeData);

                // Destroy XSQLVAR structures
                for (var i = 0; i < xsqlda.sqln; i++)
                {
                    IntPtr ptr = GetIntPtr(pNativeData, ComputeLength(i));

                    // Free	sqldata	and	sqlind pointers	if needed
                    var sqlvar = new XSQLVAR();
                    MarshalXSQLVARNativeToManaged(ptr, sqlvar, true);

                    if (sqlvar.sqldata != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(sqlvar.sqldata);
                        sqlvar.sqldata = IntPtr.Zero;
                    }

                    if (sqlvar.sqlind != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(sqlvar.sqlind);
                        sqlvar.sqlind = IntPtr.Zero;
                    }

                    Marshal2.DestroyStructure <XSQLVAR>(ptr);
                }

                // Free	pointer	memory
                Marshal.FreeHGlobal(pNativeData);

                pNativeData = IntPtr.Zero;
            }
        }