2013-10-08 54 views
2

一直在這幾個小時,不能讓它工作:(的PInvoke返回浮點

下面的代碼提供了異常「嘗試讀取或寫入受保護的內存。這通常是指示其他內存腐敗。」這是固定的,請參閱下面的更新

,但是當我改變返回類型INT,並返回一個INT價值,它的工作原理。如何使它返回一個浮動值? 謝謝。

vs2012

C++代碼

extern "C" __declspec(dllexport) 
float compute_similarity() 
{  
    return 1.01; 
} 

C#代碼

[DllImport("demo.exe", EntryPoint = "compute_similarity", CallingConvention = CallingConvention.Cdecl)] 
public static extern float compute_similarity(); 

public void Get() 
{ 
    float x = compute_similarity(); // here returns random value 
} 

======================= ==============

UPDATE

查看大衛下面的評論,問題是c#項目是針對x64,而C++針對的是Win32。將c#項目更改爲x86目標後,異常消失了。

不過從C#調用返回預期

+2

你在64位機器上嗎?我只是想知道,如果C代碼是64位環境,是否會返回一個64位的「float」(即C#代碼的雙精度值)。 –

+2

如果你明確地在C++的'float'和'compute_similarity'之間加了'__cdecl',它會起作用嗎? – dtb

+0

@DavidArno非常感謝大衛,是的,c#項目是針對x64的,C++針對的是Win32,在將c#項目更改爲x86目標後,它使異常消失,儘管它仍然返回一些隨機值而不是1.01。更新了問題。 – Xin

回答

3

一些隨機值,而不是1.01我覺得你的問題是,你的函數是一個可執行的,而不是一個DLL聲明。將您的本地代碼轉換爲庫項目並編譯DLL。

您的代碼將致電LoadLibrary,傳遞文件名demo.exe。該documentationLoadLibrary說:

LoadLibrary也可用於加載其他可執行模塊。例如,該函數可以指定一個.exe文件以獲取可在FindResourceLoadResource中使用的句柄。但是,請不要使用LoadLibrary來運行.exe文件。相反,使用CreateProcess函數。

所以你的代碼正在做你正在告訴不要做的事情。撥打LoadLibrary將成功。隨後調用GetProcAddress將成功。但是你加載的模塊不適合執行代碼。

+0

看起來似乎是合理的,但另一方面,微軟表示可以將P/Invoke轉換爲exes(請參閱Microsoft員工的回覆[此處](http://social.msdn.microsoft.com/Forums/vstudio/en-US/e5eab264-6ce8-4c60-ac6d-2b4cf37a5a8c/pinvoke-into-hosting-executable?forum=clr) - 仍然看起來值得試一試! –

+1

@MatthewWatson如果模塊已經被加載,那很好,但是問題中的代碼會在可執行文件中調用'LoadLibrary',這被記錄爲不工作:* LoadLibrary也可以用來加載其他可執行模塊。例如,函數可以指定一個.exe文件來獲取可以在FindResource或LoadResource中使用的句柄,但是,不要使用LoadLibrary來運行.exe文件,而應該使用CreateProcess函數* –

+0

@DavidHeffernan,MatthewWaston謝謝爲您的所有輸入將它固化爲dll輸出確實修復了它。雖然不知道爲什麼這有所作爲。 – Xin