如何从C#调用这个Delphi .dll函数?

4

// Delphi代码(Delphi版本:Turbo Delphi Explorer(即Delphi 2006))

function GetLoginResult:PChar;
   begin
    result:=PChar(LoginResult);
   end; 

//以下是C#代码使用上面的Delphi函数(我正在使用Unity3d,在C#中)

[DllImport ("ServerTool")]
private static extern string GetLoginResult();  // this does not work (make crash unity editor)

[DllImport ("ServerTool")] 
[MarshalAs(UnmanagedType.LPStr)] private static extern string GetLoginResult(); // this also occur errors

如何正确使用C#中的该函数?

(在Delphi中也可用,代码如下,如果 (event=1) 并且 (tag=10) 则写入 '登录结果: ' 和 GetLoginResult;)


可能会有帮助:https://dev59.com/AVTTa4cB1Zd3GeqPtpah - Christophe Geers
1个回答

8

这个字符串的内存由你的 Delphi 代码拥有,但是你的 P/Invoke 代码会导致 marshaller 调用 CoTaskMemFree 释放那个内存。

你需要告诉 marshaller 它不应该负责释放内存。

[DllImport ("ServerTool")] 
private static extern IntPtr GetLoginResult();

然后使用 Marshal.PtrToStringAnsi() 将返回值转换为C#字符串。

IntPtr str = GetLoginResult();
string loginResult = Marshal.PtrToStringAnsi(str);

您还需要确保调用约定匹配,通过声明Delphi函数为stdcall

function GetLoginResult: PChar; stdcall;

虽然对于没有参数和指针大小返回值的函数,这种调用约定不匹配并不重要。
为了使所有这些工作正常,Delphi字符串变量“LoginResult”必须是全局变量,以便在“GetLoginResult”返回后其内容仍然有效。

@Petesh,实际上并不是因为该函数没有参数且返回值在stdcall和register中处理方式相同。但最好将Delphi函数声明为stdcall。感谢您的建议。 - David Heffernan
@Stefan 发生的情况是,编组程序在返回的指针上调用 CoTaskMemFree - David Heffernan
@DavidHeffernan 感谢您的回复,但是出现了错误... 请看这些错误图片。 - creator
请返回已翻译的文本。 - creator
请阅读第一个错误信息。您不能在字段初始化器中执行此操作。您必须将代码放在方法内部。 - David Heffernan
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接