【问题标题】:Call dotNET from Delphi and return a string从 Delphi 调用 dotNET 并返回一个字符串
【发布时间】:2016-05-20 06:43:04
【问题描述】:

Delphi 应用程序如何调用导出的函数(非 COM)dotNET 程序集并让函数返回字符串?

COM 不是我的特定应用程序的可能解决方案。我可以控制通话的两端。

到目前为止我所尝试的 - Delphi 客户端

type
  TStrProc = procedure( var x: widestring); stdcall;

function TryIt: string;
var
  Handle: THandle;
  Proc: TStrProc;
  InData: widestring;
  OutData: widestring;
begin
  Handle    := LoadLibrary( 'DelphiToDotNet.dll');
  if Handle = 0 then exit;
  @Proc := GetProcAddress( Handle, 'StrProc');
  if @Proc <> nil then
    begin
    InData := 'input';
    Proc( InData);
    OutData := InData;
    end;
  FreeLibrary( Handle);
  result := OutData
end;

dotNET dll 端

public class DotNetDllClass
{
  [DllExport]
  public static string StrProc(ref string s)
  {
      return "Hello from .Net " + s;
  }
}

什么有效

我可以成功地将整数传入和传出 dotNET 过程。 我可以成功地将字符串(Delphi 端的宽字符串)传递到 dotNET 程序中。

什么不起作用

在上面两个清单中,返回的字符串参数是垃圾。访问它会导致 AV。

环境

Delphi XE7、dotNET 4、Win 7、32 位应用程序和 dll。

【问题讨论】:

    标签: c# delphi interop


    【解决方案1】:

    与Delphi匹配的C#代码应该是:

    [DllExport]
    public static void StrProc(
        [MarshalAs(UnmanagedType.BStr)] 
        ref string s
    )
    {
        s = "Hello from .Net " + s;
    }
    

    请注意,返回类型为void 以匹配您的Delphi 代码。我用UnmanagedType.BStr 匹配WideString。这是编组文本最简单的方法,因为分配是由两个编译器自动为您执行的。

    不要试图将字符串作为返回值传递给BStr。 Delphi 不使用与其他编译器相同的 ABI,请参阅 Why can a WideString not be used as a function return value for interop?

    【讨论】:

    • 那么,如果我在 StrProc 内部创建一个对象,内存管理是怎样的呢? Delphi 端会处理内存还是 C# 端?垃圾收集器会处理对象并释放内存吗?
    • 它就像任何其他 .net 对象一样,由 GC 处理
    • 让我让它工作的要点:在 C# 中使用 MarshalAs 和 ref,在 Delphi 中在参数声明中使用 var。这使它对我有用
    • @Arie Er,答案不就是这样吗?
    • 是的。答案是完美的。这更像是给我自己(和其他找到这个答案的人)的关键点。例如。 Delphi 声明中的 var 一词很容易被忽略。这就是发生在我身上的事情,因此我想知道它是如何工作的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2021-10-17
    • 2018-02-25
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    相关资源
    最近更新 更多