我正在尝试从C#导出一个函数,并使用delphi应用程序调用此函数。 被调用的函数应获取一个回调作为参数。此回调将字符串作为参数。 csharp_export_function(callbackfct(str))
我设法调用一个C#函数,该函数编写一个字符串并在delphi中使用此字符串。 我还设法使用回调作为参数调用C#函数,并使用了该回调。
但是我无法获得带有字符串作为参数运行的回调。 在回调函数中使用字符串时,在Delphi中收到访问冲突异常。该字符串似乎在那里是空的。 因此,执行了callbak,但是无法使用该字符串。
我正在使用Robert Giesecke的DllExport for C#。 Delphi XE5和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);
}
}
}
谢谢。
答案 0 :(得分:1)
您无需在此处传递参数使用out
,并且调用约定与您的委托不匹配。委托的相关代码在C#端
public delegate void strCB(string s);
在Delphi方面
TStringCallback = procedure(str: PAnsiChar); stdcall;
我一如既往地坚持使用ANSI字符串,但是如果我的代码是我个人,则我会使用Unicode。
答案 1 :(得分:0)
该代码现在可以与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);
}
}
}