[英]Passing array of struct from c# to delphi
我在VS2010中使用Robert Giesecke Unmanaged Exports 1.2.6 ,我的目標是將一系列結構從c#(.NET 3.5)傳遞給delphi(D7) 。 我不得不承認,我對德爾福並不熟悉。
我已經閱讀過這篇文章 ,但建議的答案對我不起作用:在delphi中調用func
時,CPU調試窗口打開,如果我繼續應用程序退出,無異常且沒有所需的結果。
這是我試過的代碼:
C#平台x86
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using RGiesecke.DllExport;
namespace ArrayTest
{
public class Class1
{
public struct Sample
{
[MarshalAs(UnmanagedType.BStr)]
public string Name;
}
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
Sample[] samples,
ref int len
)
{
// len holds the length of the array on input
// len is assigned the number of items that have been assigned values
// use the return value to indicate success or failure
for (int i = 0; i < len; i++)
samples[i].Name = "foo: " + i.ToString();
return 0;
}
}
}
Delphi7中
program DelphiApp;
{$APPTYPE CONSOLE}
uses
SysUtils,
ActiveX;
type
TSample = record
Name: WideString;
end;
PSample = ^TSample;
function func(samples: PSample; var len: Integer): Integer; stdcall;
external 'ArrayTest.dll';
procedure Test2;
var
samples: array of TSample;
i, len: Integer;
begin
len := 10;
SetLength(samples, len);
if func(PSample(samples), len)=0 then
for i := 0 to len-1 do
Writeln(samples[i].Name);
end;
begin
Test2();
end.
如前所述,調試器打開CPU窗口,如果我繼續應用程序退出,無異常或錯誤消息。 如果我在沒有dbugger的情況下運行它,Windows告訴我應用程序不再工作,應用程序關閉。
我錯過了什么?
更新
修改后的代碼
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
Sample[] samples,
ref int len
)
{
Console.WriteLine("return 0");
return 0;
}
procedure Test2;
var
samples: array of TSample;
i, len: Integer;
begin
len := 10;
SetLength(samples, len);
if func(PSample(samples), len)=0 then
for i := 0 to len-1 do
Writeln('D7: ', i);
end;
即使我不訪問任何一側的陣列,行為仍然是相同的。
控制台輸出: return 0
好像我發現了這個問題:
如果使用.NET 4.0或更高版本,代碼運行正常。 如果使用.NET 3.5或更低版本,則len-parameter必須按值傳遞。
請參閱MSDN文檔SizeParamIndex v3.5 :
包含大小的參數必須是按值傳遞的整數。
請參閱MSDN文檔SizeParamIndex v4.0 :
當數組作為C樣式數組傳遞時,封送程序無法確定數組的大小。 因此,要將托管數組傳遞給非托管函數或方法,必須提供兩個參數:
數組,由引用或值定義。
數組大小,由引用或值定義。
C#
[DllExport]
public static int func(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
Sample[] samples,
int len,
ref int outLen
)
{
// len holds the length of the array on input
// outLen is assigned the number of items that have been assigned values
// use the return value to indicates success and the required array size (>=0) or failure (<0)
int requiredSize = 20;
if (requiredSize < len)
{
len = requiredSize;
}
for (outLen = 0; outLen < len; outLen++)
{
samples[outLen].Name = "foo: " + outLen.ToString();
}
return requiredSize;
}
Delphi7中
function func(samples: PSample; len: Integer; var outLen: Integer): Integer; stdcall;
external 'ArrayTest.dll';
procedure Test2;
var
samples: array of TSample;
i, len: Integer;
begin
len := 0;
// query the required array size
i := func(PSample(samples), len, len);
if i>0 then
begin
len := i;
SetLength(samples, len);
if func(PSample(samples), len, len)>=0 then
for i := 0 to len-1 do
Writeln(samples[i].Name);
end;
end;
張貼在我的問題和大衛·赫弗南發布的代碼在這里只適用於.NET> = 4.0! 如果必須使用.NET <= 3.5,則必須按值傳遞數組,而不是按引用傳遞!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.