首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从C#问题调用Delphi

从C#问题调用Delphi
EN

Stack Overflow用户
提问于 2022-10-12 06:10:11
回答 1查看 130关注 0票数 1

首先:我读了很多类似的问题,尝试了很多不同的解决方案,但我无法实现与Delphi的工作。

Delphi提供了以下方法:

代码语言:javascript
运行
复制
procedure FetchData(var infoIn: INParameter; var infoOut: OUTParameter; var details: OUTDetails); stdcall; external DLL_Name;

这些类型的定义如下:

代码语言:javascript
运行
复制
type
  Info1 = record
    Param1: Byte;
    Param2: Byte;
    Param3: Byte;
    Param4: Byte;
    Param5: integer;
  end;
  PInfo1 = ^Info1;
  
  Info2 = record
    Param1: Byte;
    Param2: integer;
    Param3: integer;
    Param4: integer;
    Param5: long;
    Param6: string;
    Param7: integer;
    Param8: array [0 .. 8] of integer;
    Param9: string;
  end;
  PInfo2 = ^Info2;

  INParameter = record
    Param1: integer;
    Param2: integer;
    Param3: integer;
    Param4: Byte;
    Param5: Byte;
    Param6: Byte;
    Param7: Byte;
    Param8: Byte;
    Param9: Byte;
    Param10: Byte;
    Param11: Byte;
    Param12: Byte;
    Param13: Byte;
    Param14: Byte;
    Param15: Byte;
    Param16: Byte;
    Param17: Byte;
    Param18: Byte;
    Param19: Byte;
    Param20: Byte;
    Param21: Byte;
    Param22: Byte;
    Param23: integer;
    Param24: integer;
    Param25: Byte;
    Param26: Byte;
    Param27: Byte;
    Param28: Byte;
    Param29: Byte;
    Param30: Byte;
    Param31: Byte;
    Param32: Byte;
    Param33: integer;
    Param34: PInfo1;
    Param35: PInfo2;
  end;
  
  OUTParameter = record
    Param1: integer;
    Param2: integer;
    Param3: integer;
    Param4: integer;
    Param5: bool;
    Param6: bool;
    Param7: integer;
    Param8: integer;
    Param9: bool;
    Param10: bool;
    Param11: bool;
    Param12: bool;
    Param13: bool;
    Param14: bool;
    Param15: integer;
    Param16: integer;
    Param17: integer;
    Param18: bool;
    Param19: bool;
    Param20: integer;
  end;
  
  Pos = record
    Param1: integer;
    Param2: integer;
    Param3: Byte;
    Param4: Byte;
  end;
  
  OUTDetails = record
    Poss: array [0 .. 3, 0 .. 20] of Pos;
  end;

我将这些类型翻译成C#,如下所示:

代码语言:javascript
运行
复制
public structure Info1
{
    public Byte Param1;
    public Byte Param2;
    public Byte Param3;
    public Byte Param4;
    public int Param5;
}
    
public structure Info2
{
    public Byte Param1;
    public int Param2;
    public int Param3;
    public int Param4;
    public long Param5;
    public string Param6;
    public int Param7;
    public int[] Param8;
    public string Param9;
}
    
public structure INParameter
{
    public int Param1;
    public int Param2;
    public int Param3;
    public Byte Param4;
    public Byte Param5;
    public Byte Param6;
    public Byte Param7;
    public Byte Param8;
    public Byte Param9;
    public Byte Param10;
    public Byte Param11;
    public Byte Param12;
    public Byte Param13;
    public Byte Param14;
    public Byte Param15;
    public Byte Param16;
    public Byte Param17;
    public Byte Param18;
    public Byte Param19;
    public Byte Param20;
    public Byte Param21;
    public Byte Param22;
    public int Param23;
    public int Param24;
    public Byte Param25;
    public Byte Param26;
    public Byte Param27;
    public Byte Param28;
    public Byte Param29;
    public Byte Param30;
    public Byte Param31;
    public Byte Param32;
    public int Param33;
    public PInfo1 Param34;
    public PInfo2 Param35;
}
    
public structure OUTParameter
{
    public int Param1;
    public int Param2;
    public int Param3;
    public int Param4;
    public bool Param5;
    public bool Param6;
    public int Param7;
    public int Param8;
    public bool Param9;
    public bool Param10;
    public bool Param11;
    public bool Param12;
    public bool Param13;
    public bool Param14;
    public int Param15;
    public int Param16;
    public int Param17;
    public bool Param18;
    public bool Param19;
    public int Param20;
}
    
public structure Pos
{
    public int Param1;
    public int Param2;
    public Byte Param3;
    public Byte Param4;
}
    
public structure Details
{
    public Pos[] Poss;
}

然后,在控制台应用程序中,我添加了DLL extern方法定义:

代码语言:javascript
运行
复制
[DllImport("DelphiDLL.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern void FetchData(IntPtr paramIn,
                                      IntPtr paramOut,
                                      IntPtr detailsOut);

我尝试了不同的定义,使用:

  • ref INParameter, ref OUTParameter
  • out OUTParameter
  • [Out, MarshalAs(UnmanagedType.Struct)] out OUTParameter

最后,我指出Delphi需要一个指针,并将在其中写入数据。所以我给了IntPtr

对于输入/输出参数指针,我执行了以下操作:

代码语言:javascript
运行
复制
IntPtr pnt = Marshal.AllocHGlobal(Marshal.SizeOf(oneOUTParameter));
Marshal.StructureToPtr(oneOUTParameter, pntForOneOUTParameter, false);

并被称为FetchData(pntForINParameter, pntForOUTParameter, pntForOUTDetailParameter);

每次我最后都犯了错误:

在0x004F0928 (

:0xC0000005:访问冲突读取位置0x00002EE0 )中引发的DelphiDLL.dll异常。

你能帮帮我吗?

编辑:将ShortString替换为String,以及C#中的其他类型。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-12 20:45:43

我在代码中看到了一些互操作问题:

  • 的原始指针(如PInfo1PInfo2 )不会在C#中使用,所以用PInfo2替换它们

德尔菲中的

  • stringstring在C#中有很大的不同。在德尔菲中,string是指向字符数据的指针,因此您必须在C#端使用IntPtr。如果您需要从Delphi分配的string字段中读取数据,您可以使用Marshal.PtrToStringAnsi() (Delphi2007或更早版本)或Marshal.PtrToStringUni() (Delphi2009或更高版本)。但是,如果你需要通过德尔菲会读的string,祝你好运。您不仅必须手动为字符数据分配内存,而且还必须为字符数据之前的StrRec记录分配内存(而且该记录的内容可以根据Delphi而有所不同)。因此,通过DLL边界传递string是互操作中的一个坏主意。相反,您应该使用平面Char[]数组(或ShortString)或以空结尾的PChar指针.

  • C#数组是动态分配的,因此当固定大小的数组包含在struct中时,需要在C#侧使用MarshalAs来指定数组的大小。

Delphi中的

  • a bool大小为1字节,但在C#互操作中,默认情况下,bool被编组为4字节整数(在Delphi中为LongBool )。您需要使用MarshalAs来改变这种情况.

  • a LONG是一个4字节的整数.在大多数平台上,Delphi中的Longint大小为4字节,而在Posix 64位系统中为8字节。long在C#中总是8字节。

尽管如此,您所展示的Delphi代码将转换为更类似于C#中的以下内容:

代码语言:javascript
运行
复制
[StructLayout(LayoutKind.Sequential, Pack=8)]
public struct Info1
{
    public byte Param1;
    public byte Param2;
    public byte Param3;
    public byte Param4;
    public int Param5;
}

[StructLayout(LayoutKind.Sequential, Pack=8)]
public struct Info2
{
    public byte Param1;
    public int Param2;
    public int Param3;
    public int Param4;
    public int Param5; // long; use IntPtr or nint instead, if needed
    public IntPtr Param6; // string
    public int Param7;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=9)]
    public int[] Param8;
    public IntPtr Param9; // string
}

[StructLayout(LayoutKind.Sequential, Pack=8)]
public struct INParameter
{
    public int Param1;
    public int Param2;
    public int Param3;
    public byte Param4;
    public byte Param5;
    public byte Param6;
    public byte Param7;
    public byte Param8;
    public byte Param9;
    public byte Param10;
    public byte Param11;
    public byte Param12;
    public byte Param13;
    public byte Param14;
    public byte Param15;
    public byte Param16;
    public byte Param17;
    public byte Param18;
    public byte Param19;
    public byte Param20;
    public byte Param21;
    public byte Param22;
    public int Param23;
    public int Param24;
    public byte Param25;
    public byte Param26;
    public byte Param27;
    public byte Param28;
    public byte Param29;
    public byte Param30;
    public byte Param31;
    public byte Param32;
    public int Param33;
    public IntPtr Param34; //PInfo1
    public IntPtr Param35; //PInfo2
}
  
[StructLayout(LayoutKind.Sequential, Pack=8)]
public struct OUTParameter
{
    public int Param1;
    public int Param2;
    public int Param3;
    public int Param4;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param5;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param6;
    public int Param7;
    public int Param8;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param9;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param10;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param11;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param12;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param13;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param14;
    public int Param15;
    public int Param16;
    public int Param17;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param18;
    [MarshalAs(UnmanagedType.U1)]
    public bool Param19;
    public int Param20;
}
  
[StructLayout(LayoutKind.Sequential, Pack=8)]
public struct Pos
{
    public int Param1;
    public int Param2;
    public byte Param3;
    public byte Param4;
}
  
[StructLayout(LayoutKind.Sequential, Pack=8)]
public struct OUTDetails
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=84)]
    public Pos[] Poss;
}

[DLLImport("DLL_Name", CallingConvention = CallingConvention.StdCall)]
void FetchData(ref INParameter infoIn, ref OUTParameter infoOut, ref OUTDetails details);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74037181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档