I am trying to export a function from C# and call this function with a delphi application. The called function should get a callback as parameter. this callback takes a string as a parameter. csharp_export_function(callbackfct(str))
I managed to call a C# function which writes a string and use this string in delphi. I also managed to call a C# function with a callback as parameter and usw this callback.
But i can't get a callback with a string as parameter running. I get an access violation exception in Delphi, when using the string in the callback function. The string seems to be empty there. So, the callbak is executed, but the string cannot be used.
I am using DllExport for C# from Robert Giesecke. Delphi XE5 and VS2012.
Here is the code:
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);
}
}
}
Thanks in advance.
You don't need to use out
for parameter passing here, and the calling conventions don't match on your delegate. The relevant code for the delegate is, on the C# side
public delegate void strCB(string s);
And on the Delphi side
TStringCallback = procedure(str: PAnsiChar); stdcall;
I've stuck with using ANSI strings as you did, but I'd personally use Unicode if it were my code.