从 Delphi 调用 C# Dll-Export - 以字符串作为参数的回调 - Robert Giesecke DLLExport

Call C# Dll-Export from Delphi - Callback with String as parameter - Robert Giesecke DLLExport

我正在尝试从 C# 导出函数并使用 delphi 应用程序调用该函数。 被调用的函数应该得到一个回调作为参数。此回调将字符串作为参数。 csharp_export_function(callbackfct(str))

我设法调用了一个 C# 函数,该函数写入一个字符串并在 delphi 中使用该字符串。 我还设法调用了一个带有回调作为参数的 C# 函数,并使用了这个回调。

但我无法获得以字符串作为参数的回调 运行。 在回调函数中使用字符串时,我在 Delphi 中遇到访问冲突异常。那里的字符串似乎是空的。 所以,执行了callbak,但是字符串不能使用。

我正在使用 Robert Giesecke 的 DllExport for C#。 DelphiXE5 和 VS2012。

代码如下:

delphi:

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Button4: TButton;
    Edit4: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private

  public

  end;

  TStringCallback = procedure(out str:PAnsiChar);

  procedure strCallBack(fct: TStringCallback); cdecl; external 'csTest.dll';
var
  Form2: TForm2;

implementation

{$R *.dfm}

//*************************************************************
//callback with string
procedure writeEdit2(out str: PAnsiChar);
begin
  Form2.Edit2.Text := str;      //!! exception access violation !!
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  strCallBack(writeEdit2);
end;
//*************************************************************

end.

c#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;

namespace cs_dcsSrv
{
    public class Class1
    {
        public delegate void strCB([MarshalAs(UnmanagedType.BStr)] String s);

        [DllExport("strCallBack", CallingConvention = CallingConvention.Cdecl)]
        public static void stringCallback(strCB fct)
        {
            String str = "hello from C#";
            fct(str);
        }
    }
}

提前致谢。

您无需使用 out 进行此处的参数传递,并且调用约定与您的委托不匹配。委托的相关代码在C#端

public delegate void strCB(string s);

在Delphi这边

TStringCallback = procedure(str: PAnsiChar); stdcall;

我一直像您一样坚持使用 ANSI 字符串,但如果是我的代码,我个人会使用 Unicode。

代码现在可以根据 David 的建议运行。 不幸的是,我坚持使用 cdecl 调用约定和 delphi 端的 ansi 字符串。

Delphi:

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Button2: TButton;
    Edit2: TEdit;
    procedure Button2Click(Sender: TObject);
  private
  public
  end;
  TStringCallback = procedure(str:PAnsiChar); cdecl;

  procedure strCallBack(fct: TStringCallback); cdecl; external 'csTest.dll';
var
  Form2: TForm2;

implementation

{$R *.dfm}

//*************************************************************
//callback with string
procedure writeEdit2(str: PAnsiChar); cdecl;
begin
  Form2.Edit2.Text := str;
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
  strCallBack(writeEdit2);
end;
//*************************************************************

end.

C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;

namespace cs_dcsSrv
{
    public class Class1
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void strCB(String s);

        [DllExport("strCallBack", CallingConvention = CallingConvention.Cdecl)]
        public static void stringCallback(strCB fct)
        {
            String str = "hello from C#";
            fct(str);
        }
    }
}