C# 从Delphi调用C Dll导出-以字符串作为参数的回调-Robert Giesecke DLLExport
我正在尝试从C导出一个函数,并用delphi应用程序调用该函数。 被调用的函数应该得到一个回调作为参数。此回调将字符串作为参数。 csharp\u导出\u函数callbackfctstr 我设法调用了一个写字符串的C函数,并在delphi中使用了这个字符串。 我还设法用回调函数作为参数调用了一个C函数,并使用了这个回调函数 但我无法获取以字符串作为参数运行的回调。 在Delphi中,当在回调函数中使用字符串时,我得到一个访问冲突异常。那里的绳子好像是空的。 因此,执行callbak,但不能使用字符串 我正在使用Robert Giesecke提供的DllExport for C。Delphi XE5和VS2012 代码如下: 德尔菲:C# 从Delphi调用C Dll导出-以字符串作为参数的回调-Robert Giesecke DLLExport,c#,delphi,callback,dllexport,C#,Delphi,Callback,Dllexport,我正在尝试从C导出一个函数,并用delphi应用程序调用该函数。 被调用的函数应该得到一个回调作为参数。此回调将字符串作为参数。 csharp\u导出\u函数callbackfctstr 我设法调用了一个写字符串的C函数,并在delphi中使用了这个字符串。 我还设法用回调函数作为参数调用了一个C函数,并使用了这个回调函数 但我无法获取以字符串作为参数运行的回调。 在Delphi中,当在回调函数中使用字符串时,我得到一个访问冲突异常。那里的绳子好像是空的。 因此,执行callbak,但不能使用字
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:
提前感谢。在此处传递参数时不需要使用out,并且调用约定与您的代理不匹配。代表的相关代码是,在C端
public delegate void strCB(string s);
在德尔菲方面
TStringCallback = procedure(str: PAnsiChar); stdcall;
我和你一样坚持使用ANSI字符串,但如果是我的代码,我个人会使用Unicode 该代码现在与David的建议一起工作。 不幸的是,我坚持使用cdecl调用约定和delphi端的ansi字符串 德尔菲:
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:
呼叫约定不匹配。不需要出去。AnsiBStr与Delphi中的任何内容都不匹配。如果你第一次尝试的时候表现得很好,而不是在经历了所有的尝试和错误之后,代码现在变得一团糟,那就最好了。你能再解释一下吗?为什么调用约定不同时与cdecl匹配?AnsiBstr是测试后的休息。我正在使用Bstr。这是正确的吗?使用out对我处理字符串有效,而不使用out则不行。我也读过你要用掉的。怎么了?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.
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);
}
}
}