如何在c#中读取打包记录中的Delphi固定大小字符串数组

时间:2010-02-03 16:03:02

标签: c# delphi arrays struct marshalling

我需要将数据库中的blob字段读入c#app。

然而,使用以下方法,Delphi App将blob字段写入数据库:

 procedure WriteABlob(Blob : TBlobField; var Buffer; size : integer);
 var 
     s : String;
 begin
     setlength(s,size);
     move(buffer,s[1],Size);
     Blob.Value := S;
 end;

写入数据库的结构不是一个简单的结构,包含

之类的内容
MyVariable : Array[0..3] of String[80];

或者更糟糕的是其中一些包含

MyRecord = Packed Record
case byte of
    1: (
        iValue:Integer;
       )
    2: (
        cValue:Char;
       )
end;

我一直在尝试从数据库中读取字节,然后使用

Marshal.PtrToStructure()

将其移入struct

我的结构定义如下:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1, Size = 10710)]
    public struct MyBlobField
    {
        ...
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.AnsiBStr,SizeConst = SpecificArraySize)]
        public String[] ArrayofFixedLengthStrings;
        ...
    }

但是在调用Marshal.PtrToStructure()时出现错误:

  

无法组织战场   'ArrayofFixedLengthStrings'的类型   'MyBlobField':无效   托管/非托管类型组合   (String []必须与a配对   LPStr,LPWStr,BStr或的ArraySubType   LPTSTR)。

我想知道是否有一个我可以在CustomMarshaler上定义的属性,它可以接受与String []

的配对

任何想法如何将blob的内容读入c#?

2 个答案:

答案 0 :(得分:2)

想出来......

将结构String20声明为

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct String20
    {
        [MarshalAs(UnmanagedType.U1)]
        public byte StringSize;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
        public String Value;
    }

显然,固定长度字符串(即delphi ShortString)开头的字符串大小标识符只有1个字节。 然后将header_identifiers的定义更改为:

       [MarshalAs(UnmanagedType.ByValArray, SizeConst = max_header_identifiers)]
        public String20[] header_identifiers;

还发现Delphi Packed Boolean需要转换为

[MarshalAs(UnmanagedType.I1)]
public bool BooleanVar;

答案 1 :(得分:0)

我的第一个评论是“String [80]”是一个固定长度的字符串(在结构中应该更容易处理),在C#中你试图将它放入“String []” - 这实际上是字符串的引用(指针)。

我的下一个评论是,在最坏的情况下,你可以尝试将其读入一个字节数组,然后拉出你需要的字节并将它们操作到目标结构中。