2012-09-13 18 views
2

我已經成功地用於羅伯茨UnmanagedExportLibrary.zip從Delphi 2007託管輸出/德爾福/ .NET 4 /羅伯特捷

然而,當我重新編譯C#組件調用.NET 2/3.5組件定位到.NET 4使用VS2010時,調用會崩潰,並在ntdll.dll中產生堆棧溢出異常。 (ntdll調用ntdll)加載mscorlib/mscoreei後。

有沒有其他人把這個工作時的目標.NET 4? - 羅伯特的文件似乎暗示這應該起作用。

偉大的工作由羅伯特的方式 - 非常有用。

謝謝 Myles。

+0

也許問@RobertGiesecke自己? http://stackoverflow.com/users/35443/robert-giesecke –

+0

我們有一個Delphi 2010應用程序調用一個與.Net 4編譯的DLL。工作正常。你有什麼代碼失敗了?似乎回想起我不得不停止返回字符串作爲函數結果。只有返回的int值和任何字符串傳遞都是通過out參數完成的 - 或者類似的東西。 – shunty

+0

非常感謝那些信息 - 是的,.NET函數返回一個字符串。現在,我知道它可以與.NET 4一起工作,我會回去並花更多時間。 – myles

回答

1

數組更加棘手,因爲您需要更加小心數組的分配和銷燬。最簡潔的方法總是在調用者處分配,將數組傳遞給被調用者以使其填充數組。這種方法看起來像這樣在您的上下文:

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; 
} 

你需要指定數組需要在出方向進行編組。如果你想要兩種編組的價值,那麼你會使用In, Out而不是Out。您還需要使用MarshalAsUnmanagedType.LPArray來指示如何編組數組。而且您確實需要指定大小參數,以便編組人員知道有多少項目要回傳到非託管代碼。

,然後在德爾福方聲明的功能是這樣的:

type 
    TSample = record 
    Name: WideString; 
    end; 
    PSample = ^TSample; 

function func(samples: PSample; var len: Integer): Integer; stdcall; 
    external dllname; 

這樣稱呼它:

var 
    samples: array of TSample; 
    i, len: Integer; 
.... 
len := 10; 
SetLength(samples, len); 
if func(PSample(samples), len)=0 then 
    for i := 0 to len-1 do 
    Writeln(samples[i].Name); 

更新

由於來自Alexs [發現] [1](見下面的註釋),通過引用傳遞參數大小參數nce僅支持.net 4.在早期版本中,您需要按值傳遞大小參數索引。

我選擇通過參考在這裏將它傳遞的原因是爲了允許以下協議:

  1. 呼叫者傳遞指示數組多大的值。
  2. 被調用者通過一個值,指示已填充了多少元素。

這非常適用於.NET 4,但在早期版本中,你需要使用一個額外的參數步驟2

參考 https://stackoverflow.com/a/22507948/4339857