代码之家  ›  专栏  ›  技术社区  ›  Ohad Schneider

向非托管代码传递非空终止字符串

  •  3
  • Ohad Schneider  · 技术社区  · 14 年前

    考虑通过TCP将以下结构发送到非托管dll

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct FooMessage
    {
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
        public string foo;
    
        //More fields...
    }
    

    使用以下功能(归功于 Cheeso ):

    public byte[] RawSerialize( T item )
    {
        int rawSize = Marshal.SizeOf( typeof(T) );
        IntPtr buffer = Marshal.AllocHGlobal( rawSize );
        Marshal.StructureToPtr( item, buffer, false );
        byte[] rawData = new byte[ rawSize ];
        Marshal.Copy( buffer, rawData, 0, rawSize );
        Marshal.FreeHGlobal( buffer );
        return rawData;
    }
    

    问题:封送拆收器假定foo是一个以空结尾的字符串,而非托管的dll则不是,而是实际使用最后一个字符(封送拆收器始终为空)。

    有什么想法吗?

    澄清 :我不能只将sizeconst更改为43,因为我需要维护消息的总大小以及结构中下一个字段的位置(根据现有ICD)

    3 回复  |  直到 14 年前
        1
  •  2
  •   Ohad Schneider    14 年前

    由于没有发布其他答案,以下是 workaround 我找到了

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct FooMessage
    {
        // use this for non-null-terminated strings
        // use default encoder to convert to and from string
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=42)]
        public char[] foo;
    
        //More fields...
    }
    

    也是一个 similar TCP专家Stephen Cleary的解决方案

        2
  •  1
  •   Reinstate Monica    9 年前

    可以使用structlayout(layoutkind.explicit…)并用[fieldoffset]标记每个字段( n )这将允许您将sizeconst值增加到43, 而且仍然 将下一个字段标记为从偏移量42开始。封送拆收器将封送42个字符的字符串,并忽略追加空终止符的第43个字节。

        3
  •  0
  •   Pete Wilson    14 年前

    您有两个,而且只有两个选择:

    1. 使DLL了解NUL终止的字符串;或
    2. 将字符计数与消息一起发送,并使DLL了解该计数。

    一个或另一个,选你的。

    -B