C#错误:无法使用未固定表达式中包含的固定大小缓冲区

时间:2011-06-30 17:14:53

标签: c# delphi interop

我正在努力使用C#程序从数据库中读取二进制记录。这些记录是用Borland Delphi创建的。这是一个例子:

// Delphi record definition
  tBowler_Rec = Record
  public
    gender          : tGender;
    bowler_num      : byte;
    name            : tString32;
    initials        : String[3];
    ...
// Corresponding C# definition (unmanaged code)
    [StructLayout(LayoutKind.Sequential, Pack=4)]
    public unsafe struct tBowler_Rec
    {
        public tGender gender;
        public byte bowler_num;
        public fixed byte name[32];
        public fixed byte initials[3];
        ...

我实际上能够从SQL Server数据库中读取这个二进制结构,并在Visual Studio调试器中查看数据。好极了!我可以毫无问题地访问“gender”和“bowler_num”等字段。耶!

问:如何将“名称”变成C#字符串?

示例名称是“ASHTON”。它在内存中看起来像这样:

\0x6ASHTON\0x0\0x0...

以下是我尝试访问它的方式:


[StructLayout(LayoutKind.Sequential, Pack=4)]
public unsafe struct tBowler_Rec
{
    public tGender gender;
    public byte bowler_num;
    public fixed byte name[32];
    ...
    public string Name
    {
        get
        {
            StringBuilder sb = new StringBuilder();
            int ilen = name[0];
            for (int i = 1; i <= ilen; i++)
                sb.Append(name[i]);
            return sb.ToString();
        }
    }

我收到了这个错误:

  

错误:您不能使用未固定的固定大小缓冲区   表达式。尝试使用fixed语句。

帮助?????

提前谢谢!

4 个答案:

答案 0 :(得分:2)

由于我对Delphi不是很熟悉所以我不能在tString32字段给你一个直接答案。它似乎是UnmanagedType.AnsiBStr

如果是这种情况,我会选择这样的事情:

[StructLayout(LayoutKind.Sequential, Pack=4)]
public struct tBowler_Rec
{
    public tGender gender;
    public byte bowler_num;
    [MarshalAs(UnmanagedType.AnsiBStr)]
    public string name;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public char[] initials;

还要看看我是如何进行initials封送的。如果tString不是AnsiBStr,这将是从名称封送字符的更好方法。

我还想表明我已从结构声明中删除了固定和不安全的指令,因为这对于您尝试执行的操作不是必需的。

答案 1 :(得分:2)

尝试

Encoding.ASCII.GetString(name, 1, name[0]);

答案 2 :(得分:1)

以原始格式存储的字符串不是“空终止”(C样式字符串)。

原始格式为'char count Then Count chars =&GT; 0x6 =字符计数,A = 0 S = 1 H = 2 T = 3 O = 4 N = 5.

您尝试读取Chars,直到遇到null char。但是没有null char,它不是一个以null结尾的字符串。您必须为此设置自定义数据连接器或转换数据库。

答案 3 :(得分:0)

我在这里找到答案: Fixed size buffer cannot be directly used from "this" object

解决方案:

    [StructLayout(LayoutKind.Sequential, Pack=4)]
    public unsafe struct tBowler_Rec
    {
        public tGender gender;
        public byte bowler_num;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)]
        public byte[] name;
        ...
        public string Name
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                int ilen = name[0];
                for (int i = 1; i <= ilen; i++)
                    sb.Append(name[i]);
                return sb.ToString();
            }
        }

Vladimir绝对走在正确的轨道上:根本问题是我需要将这个Delphi数组视为值类型,而不是C#(引用类型)数组。解决方案是“MarshalAs(UnmanagedType.ByValArray)”/

谢谢大家!