简体   繁体   中英

C# Structs to VB6 and vice versa

I am trying to dump data from a C# structure and then loading the data to a VB6 structure. This is the current code: C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace MarshalTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct myStruct
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
            public string str;
            [MarshalAs(UnmanagedType.I4)]
            public int integer; // VB6 long
            [MarshalAs(UnmanagedType.I2)]
            public Int16 int16; // VB6 Integer
            [MarshalAs(UnmanagedType.I1)]
            public byte b;
            [MarshalAs(UnmanagedType.VariantBool)]
            public bool flag;

        }

        private void button1_Click(object sender, EventArgs e)
        {
            myStruct strc = new myStruct();
            //String.Format("{0,6}", strc.str);
            strc.str = "Abhi";
            strc.integer = 49125071;
            strc.int16 = 0491;
            strc.b = 4;
            strc.flag = true;
            Type outputType = typeof(myStruct).IsEnum ? Enum.GetUnderlyingType(typeof(myStruct)) : typeof(myStruct);

            byte[] bArr = new byte[Marshal.SizeOf(strc)];
            IntPtr ptr = IntPtr.Zero;
            try
            {
                ptr = Marshal.AllocHGlobal(Marshal.SizeOf(strc));
                Marshal.StructureToPtr(strc, ptr, false);
                Marshal.Copy(ptr, bArr, 0, Marshal.SizeOf(strc));

                using (FileStream fs =  File.Create("C:\\users\\abhijeet\\desktop\\data.dat"))
                {
                    fs.Write(bArr, 0, bArr.Length);
                    fs.Close();
                }

                // WM_APP is 0x8000
                //IntPtr retval = SendMessage(m_HostWindow, 0x8000, IntPtr.Zero, ptr);
            }
            finally
            {
                if (ptr != IntPtr.Zero)
                {
                    Marshal.DestroyStructure(ptr, typeof(myStruct));
                    Marshal.FreeHGlobal(ptr);
                }
            }
        }

        private string checkFixedLength(string str, int length)
        {
            if (str.Length > length)
            {
                return str.Substring(0, length); 
            }
            return str;
        }

    }
}

VB6

Option Explicit
'Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal ByteLen As Long)
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function HeapAlloc Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" (ByVal hHeap As Long, ByVal dwFlags As Long, lpMem As Any) As Long

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) str As String l As Long i As Integer b As Byte flag As Boolean End Type

Private Sub cmdCommand1_Click()
    Dim t As myType, f As Long
    Dim bArr() As Byte

    Debug.Print LenB(t)

    ReDim bArr(LenB(t) - 1)
    f = FreeFile
    Open "c:\users\abhijeet\desktop\data.dat" For Binary As #f
    Get #f, , bArr()
    Close #f

    Dim ptr As Long, hHeap As Long
    hHeap = GetProcessHeap
    ptr = HeapAlloc(hHeap, 0, LenB(t))

    CopyMemory ByVal VarPtr(t), ByVal VarPtr(bArr(0)), LenB(t)

    Debug.Print t.str
    Debug.Print t.l
    Debug.Print t.i
    Debug.Print t.b
    Debug.Print t.flag
End Sub

For some reason the size of the structure always return 16 even though the size constant has been set. Am I missing something for the structure?

Thanks

The structure size won't include the string contents unless it is a fixed size and not a pointer.

[MarshalAs(UnmanagedType.ByValTStr, SizeConst=6)]
public string str;

(Note that the documentation for ByValTStr says it differs from Vb6 with null terminators)

On the VB6 side, you'll also want to make it a fixed length string to include the contents inline

str As String * 6

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM