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

C#错误:无法使用非固定表达式中包含的固定大小缓冲区,c#,delphi,interop,C#,Delphi,Interop,我正在与一个从数据库读取二进制记录的C#程序斗争。这些记录是用Borland Delphi创建的。下面是一个例子: // Delphi record definition tBowler_Rec = Record public gender : tGender; bowler_num : byte; name : tString32; initials : String[3]; ...

我正在与一个从数据库读取二进制记录的C#程序斗争。这些记录是用Borland Delphi创建的。下面是一个例子:

// Delphi record definition tBowler_Rec = Record public gender : tGender; bowler_num : byte; name : tString32; initials : String[3]; ... //德尔菲记录定义 tBowler_Rec=记录 公众的 性别:tGender; bowler_num:字节; 名称:tString32 ;; 缩写:字符串[3]; ... //对应的C#定义(非托管代码) [StructLayout(LayoutKind.Sequential,Pack=4)] 公共不安全结构tBowler\u Rec { 公共性别; 公共字节bowler_num; 公共固定字节名[32]; 公共固定字节首字母[3]; ... 实际上,我能够从SQL Server数据库中读取此二进制结构,并在Visual Studio调试器中查看数据。耶!我能够毫无问题地访问“性别”和“bowler_num”等字段。耶

问:如何将“name”转换为C#字符串

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

\0x6ASHTON\0x0\0x0... \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();
        }
    }

[StructLayout(LayoutKind.Sequential,Pack=4)]
公共不安全结构tBowler\u Rec
{
公共性别;
公共字节bowler_num;
公共固定字节名[32];
...
公共字符串名
{
得到
{
StringBuilder sb=新的StringBuilder();
int-ilen=name[0];

对于(int i=1;i,因为我对Delphi不是很熟悉,所以我无法在
tString32
字段上给您一个直接的答案。它似乎是

如果是这样的话,我会选择这样的方式:

[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;
再看看我是如何处理
首字母的
封送的。如果tString不是AnsiBStr,那么这将是从name封送字符的更好方法


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

因为我对Delphi不是很熟悉,所以我无法在
tString32
字段上给您一个直接的答案。它似乎是

如果是这样的话,我会选择这样的方式:

[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;
再看看我是如何处理
首字母的
封送的。如果tString不是AnsiBStr,那么这将是从name封送字符的更好方法


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

以原始格式存储的字符串不是“以null结尾”(C样式字符串)

原始格式是“字符计数”,然后是“字符计数” =>0x6=字符数,A=0s=1h=2t=3o=4n=5


您尝试读取字符,直到遇到空字符。但是没有空字符,它不是以空结尾的字符串。您必须为此设置自定义数据播放机或转换数据库。

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

原始格式是“字符计数”,然后是“字符计数” =>0x6=字符数,A=0s=1h=2t=3o=4n=5

您尝试读取字符,直到遇到空字符。但是没有空字符,它不是以空字符结尾的字符串。您必须为此设置自定义数据播放机或转换数据库。

尝试

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

我在这里找到了答案:

解决方案:

[StructLayout(LayoutKind.Sequential,Pack=4)]
公共不安全结构tBowler\u Rec
{
公共性别;
公共字节bowler_num;
[Marshallas(UnmanagedType.ByValArray,SizeConst=32)]
公共字节[]名称;
...
公共字符串名
{
得到
{
StringBuilder sb=新的StringBuilder();
int-ilen=name[0];
对于(int i=1;i我在这里找到了答案:

解决方案:

[StructLayout(LayoutKind.Sequential,Pack=4)]
公共不安全结构tBowler\u Rec
{
公共性别;
公共字节bowler_num;
[Marshallas(UnmanagedType.ByValArray,SizeConst=32)]
公共字节[]名称;
...
公共字符串名
{
得到
{
StringBuilder sb=新的StringBuilder();
int-ilen=name[0];

对于(int i=1;i为什么要使用
不安全的
固定的
?我不明白为什么需要这样做。对我来说,这看起来像是一个非常常规的P/Invoke。检查这个问题TString32是Delphi中的自定义类型,它的声明是什么?我猜字符串[32]。你真的确定要发送
字符串[N]
Delphi和C#?
\0x6ASHTON\0x0\0x0
之间的实例显然是一个很好的ol'Turbo Pascal字符串,其中长度字节的前缀最多为255个字符字节。为什么要使用
不安全的
固定的
?我不明白为什么需要这样做。对我来说,它看起来像是一个非常常规的P/调用。检查这个问题TString32是否正确Delphi中的自定义类型,它的声明是什么?我猜是字符串[32]。是否确实要发送
String[N]
Delphi和C#?
\0x6ASHTON\0x0\0x0之间的实例显然是一个很好的ol'Turbo Pascal字符串,其中长度字节的前缀最多为255个字符字节。很好的观察到它是长度前缀。但是您不需要自定义转换器,.NET为此提供了Asciencoding类。很好的观察到它是长度前缀。但是您不需要自定义转换器,.NET为此提供了AscienceODing类。这是正确的,它考虑了第一个字节的长度,这是Delphi中典型的
ShortString
数据类型。Paulsm这里-下一票不是我,Ben。除了“GetString()”之外,我选择了另一个路径,但我感谢您的反馈。谢谢!这是正确的,它考虑了第一个字节的长度,这是Delphi中典型的
ShortString
数据类型。Paulsm her [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(); } }