tags:

views:

47

answers:

2

given this structure in c#:

[StructLayout(LayoutKind.Sequential)]
unsafe public struct AppVPEntry
{
    public int Num;
    public fixed byte CompName[256];
    public int VPBeginAddress;
}

Whats the easiest way to copy a string ("c:\path\file.txt") to the fixed length buffer 'CompName'. This is in a structure thats being sent over to an archaic DLL that we've got no choice but to use. Ideally I'd love to use a .NET function but since it's fixed which implies 'unsafe' I know I'm limited here. A more generic function would help since we've got strings like this all over the DLL import space.

+1  A: 
// C# to convert a string to a byte array.
public static byte[] StrToByteArray(string str)
{
    System.Text.ASCIIEncoding  encoding = new System.Text.ASCIIEncoding();
    return encoding.GetBytes(str);
}

You probably want to check to see if the size of the string isn't longer than the size of the buffer.

Brian T Hannan
I've already tried this and it doesn't work. This will return a managed byte structure, whilst the 'fixed' and 'unsafe' in the structure definition implies unmanaged. Thanks anyway...
Gio
A: 

Try this out. Use an IntPtr in your DllImport wherever you might pass a VPEntry. Pass the "unmanaged" field wherever you call your DLL method.

public sealed class AppVPEntry : IDisposable {

    [StructLayout(LayoutKind.Sequential, Size = 264)]
    internal struct _AppVPEntry {
        [MarshalAs(UnmanagedType.I4)]
        public Int32 Num;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
        public Byte[] CompName;
        [MarshalAs(UnmanagedType.I4)]
        public Int32 VPBeginAddress;
    }

    private readonly IntPtr unmanaged;
    private readonly _AppVPEntry managed = new _AppVPEntry();

    public AppVPEntry(Int32 num, String path, Int32 beginAddress) {
        this.managed.Num = num;
        this.managed.CompName = new byte[256];
        Buffer.BlockCopy(Encoding.ASCII.GetBytes(path), 0, this.managed.CompName, 0, Math.Min(path.Length, 256));
        this.managed.VPBeginAddress = beginAddress;
        this.unmanaged = Marshal.AllocHGlobal(264);
        Marshal.StructureToPtr(this.managed, this.unmanaged, false);
    }

    public void Dispose() {
        Marshal.FreeHGlobal(this.unmanaged);
    }
}
Mark H