2012-06-24 70 views
4

// Delphi代碼(DELPHI版本:渦輪德爾福資源管理器(這是2006年德爾福))如何從C#中調用這個delphi .dll函數?

function GetLoginResult:PChar; 
    begin 
    result:=PChar(LoginResult); 
    end; 

// C#代碼使用上述Delphi函數(我用unity3d,中,C#)

[DllImport ("ServerTool")] 
private static extern string GetLoginResult(); // this does not work (make crash unity editor) 

[DllImport ("ServerTool")] 
[MarshalAs(UnmanagedType.LPStr)] private static extern string GetLoginResult(); // this also occur errors 

什麼是在C#中使用該功能的正確方法?

(用於在Delphi中也使用,代碼等, 如果(事件= 1)和(標籤= 10)然後writeln( '登錄結果:',GetLoginResult);)

+0

可能的幫助:http://stackoverflow.com/questions/5086645/how-to-use-delphi-dllwith-pchar-type-in​​-c-sharp –

回答

8

的存儲器字符串由您的Delphi代碼擁有,但您的p/invoke代碼將導致編碼器在該內存上調用CoTaskMemFree

你需要做的是告訴編組人員不應承擔釋放內存的責任。

[DllImport ("ServerTool")] 
private static extern IntPtr GetLoginResult(); 

然後使用Marshal.PtrToStringAnsi()將返回值轉換爲C#字符串。

IntPtr str = GetLoginResult(); 
string loginResult = Marshal.PtrToStringAnsi(str); 

你也應該確保調用約定比賽通過聲明Delphi函數是stdcall

function GetLoginResult: PChar; stdcall; 

雖然恰巧這個調用約定不匹配不適合的事函數沒有參數和指針大小的返回值。

爲了使所有這些工作,德爾福字符串變量LoginResult必須是一個全局變量,以便它的內容在GetLoginResult返回後有效。

+0

調用約定是否也適用於這種情況? – Petesh

+0

@Petesh事實上沒有,因爲該函數沒有參數和返回值處理相同的stdcall和註冊。但是將Delphi函數聲明爲stdcall會更好。感謝那。 –

+0

我很確定,如果您將DllImport函數的返回值定義爲字符串,則編組人員會按照msdn(http://msdn.microsoft.com/zh-cn/library/e765dyyy.aspx)中所述正確處理它。 –