6

我有一个 C# DLL,它使用由 Inno Setup Pascal 脚本直接调用的Unmanaged Exports公开一个函数。这个函数需要返回一个字符串给 Inno Setup。我的问题是我怎样才能做到这一点?
我首选的方法是将缓冲区从 Inno Setup 传递给 C# 函数,该函数将返回此缓冲区内的字符串。我想出了这段代码:

C#函数:

[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
static int Test([Out, MarshalAs(UnmanagedType.LPWStr)] out string strout)
{
   strout = "teststr";
   return strout.Length;
}

Inno 设置脚本:

function Test(var res: String):Integer; external 'Test@files:testdll.dll stdcall';

procedure test1; 
var
    Res: String;
    l: Integer;
begin
    SetLength(Res,256);
    l := Test(Res);
    { Uncommenting the following line causes an exception }
    { SetLength(Res,l); }
    Log('"Res"');
end;

当我运行此代码时,Res变量为空(我在日志中看到“”)

如何从此 DLL 返回字符串?

请注意,我使用的是 Unicode 版本的 Inno Setup。我也不想使用 COM 调用此函数,也不想在 DLL 中分配缓冲区并将其返回给 Inno Setup。

4

1 回答 1

8

我建议您使用BSTR类型,它曾经是互操作函数调用的数据类型。在 C# 端,您将字符串编组为UnmanagedType.BStr类型,在 Inno Setup 端,您将使用WideString与类型兼容的BSTR. 因此,您的代码将更改为此(另请参阅Marshalling sampleUnmanaged Exports 文档的章节):

[DllExport("Test", CallingConvention = CallingConvention.StdCall)]
static int Test([MarshalAs(UnmanagedType.BStr)] out string strout)
{
    strout = "teststr";
    return 0; // indicates success
}

在 Inno Setup 方面使用WideStringto 这个:

[Code]
function Test(out strout: WideString): Integer;
  external 'Test@files:testdll.dll stdcall';

procedure CallTest;
var
  retval: Integer;
  str: WideString;
begin
  retval := Test(str);
  { test retval for success }
  Log(str);
end;
于 2013-12-26T00:35:20.517 回答