将字符串数组从 C# 返回到 Inno Setup
Returning a string array from C# to Inno Setup
我正在使用 Robert Giesecke 的 Unmanaged Exports NuGet 并在 C# 中使用以下方法:
[DllExport("DummyMethod", CallingConvention = CallingConvention.StdCall)]
public static void DummyMethod(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out string[] test, out int count)
{
count = 3;
test = new[] {"test1", "test2", "test3"};
}
在 Inno Setup 中,这是我的代码:
[Code]
procedure DummyMethod(out Test: TArrayOfString; out Count: Integer);
external 'DummyMethod@files:MyDll.dll stdcall';
procedure InitializeWizard();
var Test : TArrayOfString;
var Count : Integer;
begin
DummyMethod(Test, Count);
MsgBox(Test[0], mbError, MB_OK);
end;
出于某种原因,Count
始终为 0 而 Test
始终为空。
我查看了几个示例,但找不到 Inno Setup 从 C# DLL 获取字符串数组的示例。
带有 string
的 UnmanagedType.LPArray
映射到指向 char 的指针数组(C 风格 char**
)。在 Unicode Pascal 脚本中是 array of PAnsiChar
。 Pascal 脚本无法神奇地将其转换为 TArrayOfString
(array of string
).
你可以这样转换:
type
TArrayOfPAnsiChar = array of PAnsiChar;
procedure DummyMethod(out StringPtrs: TArrayOfPAnsiChar; out Count: Integer);
external 'DummyMethod@files:ArrayInno.dll stdcall';
function DummyMethodWrapper: TArrayOfString;
var
ArrayOfPAnsiChar: TArrayOfPAnsiChar;
I, Count: Integer;
begin
DummyMethod(ArrayOfPAnsiChar, Count);
SetArrayLength(Result, Count);
for I := 0 to Count - 1 do
begin
Result[I] := ArrayOfPAnsiChar[I];
end;
end;
(使用 Unicode Inno Setup 测试)
旁注:
- 不清楚,谁为
TArrayOfAnsiChar
和单个字符数组分配内存。我充其量闻到内存泄漏的味道。
- 您可能想要使用 16 位字符缓冲区,而不是 8 位字符缓冲区以允许完整的 Unicode。但请注意,这在 Pascal 脚本中更难实现,因为它缺少 16 位字符指针类型。
可以编组 BSTR
/WideString
的数组,这应该允许完整的 Unicode。
在 C# 中:
[DllExport("ReturnsArrayOfStrings", CallingConvention.StdCall)]
public static void ReturnsArrayOfStrings(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.BStr, SizeParamIndex = 1)] out string[] values,
out int numValues)
{
values = new[] { "one", "two", "three" };
numValues = values.Length;
}
在 Inno 设置中:
type
TArrayOfWideString = array of WideString;
procedure ReturnsArrayOfStrings(out values: TArrayOfWideString; out numValues: Integer);
external 'ReturnsArrayOfStrings@files:Thing.dll stdcall';
procedure DoAThing;
var
values: TArrayOfWideString;
numValues, i: Integer;
begin
ReturnsArrayOfStrings(values, numValues);
for i := 0 to numValues - 1 do
begin
Log(values[i]);
end;
end;
我正在使用 Robert Giesecke 的 Unmanaged Exports NuGet 并在 C# 中使用以下方法:
[DllExport("DummyMethod", CallingConvention = CallingConvention.StdCall)]
public static void DummyMethod(
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out string[] test, out int count)
{
count = 3;
test = new[] {"test1", "test2", "test3"};
}
在 Inno Setup 中,这是我的代码:
[Code]
procedure DummyMethod(out Test: TArrayOfString; out Count: Integer);
external 'DummyMethod@files:MyDll.dll stdcall';
procedure InitializeWizard();
var Test : TArrayOfString;
var Count : Integer;
begin
DummyMethod(Test, Count);
MsgBox(Test[0], mbError, MB_OK);
end;
出于某种原因,Count
始终为 0 而 Test
始终为空。
我查看了几个示例,但找不到 Inno Setup 从 C# DLL 获取字符串数组的示例。
带有 string
的 UnmanagedType.LPArray
映射到指向 char 的指针数组(C 风格 char**
)。在 Unicode Pascal 脚本中是 array of PAnsiChar
。 Pascal 脚本无法神奇地将其转换为 TArrayOfString
(array of string
).
你可以这样转换:
type
TArrayOfPAnsiChar = array of PAnsiChar;
procedure DummyMethod(out StringPtrs: TArrayOfPAnsiChar; out Count: Integer);
external 'DummyMethod@files:ArrayInno.dll stdcall';
function DummyMethodWrapper: TArrayOfString;
var
ArrayOfPAnsiChar: TArrayOfPAnsiChar;
I, Count: Integer;
begin
DummyMethod(ArrayOfPAnsiChar, Count);
SetArrayLength(Result, Count);
for I := 0 to Count - 1 do
begin
Result[I] := ArrayOfPAnsiChar[I];
end;
end;
(使用 Unicode Inno Setup 测试)
旁注:
- 不清楚,谁为
TArrayOfAnsiChar
和单个字符数组分配内存。我充其量闻到内存泄漏的味道。 - 您可能想要使用 16 位字符缓冲区,而不是 8 位字符缓冲区以允许完整的 Unicode。但请注意,这在 Pascal 脚本中更难实现,因为它缺少 16 位字符指针类型。
可以编组 BSTR
/WideString
的数组,这应该允许完整的 Unicode。
在 C# 中:
[DllExport("ReturnsArrayOfStrings", CallingConvention.StdCall)]
public static void ReturnsArrayOfStrings(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.BStr, SizeParamIndex = 1)] out string[] values,
out int numValues)
{
values = new[] { "one", "two", "three" };
numValues = values.Length;
}
在 Inno 设置中:
type
TArrayOfWideString = array of WideString;
procedure ReturnsArrayOfStrings(out values: TArrayOfWideString; out numValues: Integer);
external 'ReturnsArrayOfStrings@files:Thing.dll stdcall';
procedure DoAThing;
var
values: TArrayOfWideString;
numValues, i: Integer;
begin
ReturnsArrayOfStrings(values, numValues);
for i := 0 to numValues - 1 do
begin
Log(values[i]);
end;
end;