【问题标题】:How to call this delphi .dll function from C#?如何从 C# 调用这个 delphi .dll 函数?
【发布时间】:2012-06-24 06:51:19
【问题描述】:

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

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

//使用上面delphi函数的C#代码(我用的是unity3d,inside,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中使用,代码就像, if (event=1) and (tag=10) then writeln('登录结果:',GetLoginResult); )

【问题讨论】:

标签: c# delphi pinvoke


【解决方案1】:

字符串的内存归您的 Delphi 代码所有,但您的 p/invoke 代码将导致编组器在该内存上调用 CoTaskMemFree

你需要做的是告诉编组器它不应该负责释放内存。

[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。谢谢你。
  • 我很确定,如果您将 DllImport 函数的返回值定义为字符串,则编组器会按照 msdn (msdn.microsoft.com/en-us/library/e765dyyy.aspx) 中的说明正确处理它。
  • @Stefan 发生的情况是编组器在您返回的指针上调用 CoTaskMemFree
  • @DavidHeffernan 感谢您的回复,但这会发生错误...请参阅此错误图片,
猜你喜欢
  • 2011-07-15
  • 1970-01-01
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 2015-07-28
相关资源
最近更新 更多