You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#创建结构体数组指针适配Delphi插件时遇CS0错误求助

解决C#中创建指向Delphi结构体数组指针的问题

咱先拆解下你遇到的问题:跨语言(Delphi→C#)传递结构体指针时,不仅要处理C#的unsafe代码限制,还要保证结构体的内存布局和Delphi完全匹配,不然肯定会报错或者内存访问异常。

为什么你的代码会报错?

你写的public unsafe TDB* DBPointer;报错,主要有两个核心原因:

  1. C#默认禁用unsafe代码:项目默认不允许使用指针这类非托管操作,必须手动开启。
  2. 结构体定义不兼容非托管内存:你用了C#的string类型,这是托管对象,但Delphi传递的非托管内存里,字符串是指针类型(比如PWideChar),直接用string会导致内存布局不匹配,编译器直接报错。

一步步解决问题

1. 开启Unsafe代码支持

首先得让项目允许unsafe代码:

  • 右键你的C#项目 → 选择「属性」
  • 切换到「生成」标签页
  • 勾选「允许不安全代码」选项(如果是.NET Core/.NET 5+,也可以直接在项目文件的<PropertyGroup>里加<AllowUnsafeBlocks>true</AllowUnsafeBlocks>)

2. 修正结构体定义(匹配Delphi内存布局)

必须保证C#的结构体和Delphi的结构体内存字节完全对齐,还要把托管的string换成非托管的IntPtr(对应Delphi的字符串指针)。给结构体加上StructLayout属性强制顺序布局:

using System.Runtime.InteropServices;

// 匹配Delphi的TRecord结构体,CharSet根据Delphi字符串类型调整(Unicode对应Delphi 2009+的string)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TRecord
{
    // 对应Delphi的PWideChar/UnicodeString指针,不能直接用C# string
    public IntPtr Key;
    public IntPtr Value;
}

// 匹配Delphi的TDB结构体,保证字段顺序和内存对齐一致
[StructLayout(LayoutKind.Sequential)]
public struct TDB
{
    public int Count;
    // 这里是指向TRecord数组第一个元素的指针,不是C#的托管数组
    public IntPtr Records;
}

3. 在Unsafe代码中处理指针

Delphi传递过来的指针,在C#里先接收为IntPtr类型,然后在unsafe块里转换成TDB*,再遍历数组并转换字符串:

// 假设Delphi传递的指针通过这个方法接收
unsafe void ProcessDelphiDatabase(IntPtr delphiDbPtr)
{
    // 将IntPtr转换为TDB指针
    TDB* db = (TDB*)delphiDbPtr.ToPointer();
    
    // 获取数组长度
    int recordCount = db->Count;
    // 获取TRecord数组的指针
    TRecord* records = (TRecord*)db->Records;
    
    // 遍历数组,把IntPtr转换为C#字符串
    for (int i = 0; i < recordCount; i++)
    {
        // 根据Delphi字符串类型选择转换方法:PtrToStringUni对应Unicode,PtrToStringAnsi对应ANSI
        string key = Marshal.PtrToStringUni(records[i].Key);
        string value = Marshal.PtrToStringUni(records[i].Value);
        
        // 这里处理你的业务逻辑
        Console.WriteLine($"Key: {key}, Value: {value}");
    }
}

关键注意点

  • 确认Delphi结构体布局:如果Delphi里的TDB.Records是动态数组(array of TRecord),那它的内存结构和直接的指针不同(动态数组开头有引用计数和长度),这时候你需要调整C#的结构体定义,或者让Delphi那边传递指向数组第一个元素的指针+长度(也就是你现在的Count字段的用法)。
  • 字符串编码匹配:如果Delphi用的是ANSI字符串,把CharSet.Ansi和Marshal.PtrToStringAnsi对应上,避免乱码。

内容的提问来源于stack exchange,提问作者PersonaNonGrata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:55:12