原结构体如下:
typedef struct 
{
  LONG       num_tables;    /* number of tables */
  CHAR       **tables;      /* table names */
  CHAR       *where;        /* where clause */
}SE_SQL_CONSTRUCT;现在需要在c#中通过平台调用使用这个结构体,更具体地说,有一个函数的参数是SE_SQL_CONSTRUCT*类型的:
extern LONG SE_stream_query(SE_STREAM stream, SHORT num_columns,const CHAR **columns, const SE_SQL_CONSTRUCT *construct);
说明一下,这个函数的参数中用SE_SQL_CONSTRUCT的指针不是为了获取输出值,而就是纯粹一个输入参数。
现在我在c#中改写这个结构体遇到了问题,我觉得里面的那个未知长度的字符串数组很难“对齐”,写了下面这个,但显然是错误的:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal struct SeSqlConstruct
{
  public System.Int32 num_tables;
  public String[] tables;
  public String where;
}向高手请教,怎么重新定义这个结构体才是正确的?非常感谢!
如果能把前面的那个函数的重新定义的格式也给出那就更是万分感谢啦:)

解决方案 »

  1.   

    have a try!using System.Text;[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    internal struct SeSqlConstruct
    {
    public int num_tables;
    [MarshalAs(UnmanagedType.LPArray)]
    public StringBuilder[] tables;
    public StringBuilder where;
    }使用的时候,要记得初始化StringBuilder
      

  2.   

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    internal struct SeSqlConstruct
    {
      public System.Int32 num_tables;
      public System.IntPtr tables;
      public String where;
    }
      

  3.   

    OK Thank Knight94 and hdt!!let me have a try...
      

  4.   

    use hdt's or this definition:struct SeSqlConstruct
    {
        public int num_tables;
        public IntPtr[] tables;
        public string where;
    }test:Console.WriteLine(Marshal.SizeOf(typeof(SeSqlConstruct))); // 12// prepare the data
    SeSqlConstruct construct = new SeSqlConstruct();
    string[] tables = new string[] { "1", "2", "3", "4", "5" };
    construct.num_tables = tables.Length;
    construct.tables = new IntPtr[tables.Length];
    for (int i = 0; i < tables.Length; i++)
    {
        construct.tables[i] = Marshal.StringToHGlobalAuto(tables[i]); 
        // - or -
        // Marshal.StringToHGlobalAnsi
        // Marshal.StringToHGlobalUni
    }
    construct.where = "where?";// call function SE_stream_query// clean up unmanaged resources
    for (int i = 0; i < tables.Length; i++)
    {
        Marshal.FreeHGlobal(construct.tables[i]);
    }
    Console.ReadLine();
      

  5.   

    Knight94's approach is wrong, cos the marshaller will not recognize the array of StringBuilder.