2013-05-31 28 views
1

我工作在C#,我需要使用此功能從C++ DLL:C#的DllImport和編組字符**

extern "C" char IMPEXP __stdcall service_GetParameter (const char* parameter, const int value_lenght, char** value); 

我在C用它++代碼如下:

char *val = new char[256]; 
service_GetParameter("firmware_version", 255, &val); 
AnsiString FirmwareVersion = val; 
delete[] val; 

如何導入此函數並在c#中使用它?

在此先感謝

+0

僅供參考,我認爲你的C++是有點狡猾。什麼'service_GetParameter'正在做的是通過'* value'返回一個指向字符的指針。所以你的'delete [] val'會刪除返回的指針,而不是你分配的原始內存。如果沒有'new'和'delete',只寫'char * val = 0',你會更好。 – TooTone

+0

我不認爲有一個有效的答案,不知道更多關於'service_GetParameter'函數。它分配內存嗎?或者它可能會返回一個指向某個內部字符串的指針?如果調用者必須分配內存,爲什麼使用'char **'? – Dirk

+0

service_GetParameter不分配內存。調用者必須分配內存,調用service_GetParameter並釋放內存(在C++中使用delete [])。 – LukeT

回答

2

如果這個函數分配內存,並讓負責釋放它的調用者,恐怕你得手動管理:將該參數聲明爲ref IntPtr,並使用Marshal類的方法獲取帶有指向數據副本的字符串。

然後調用相應的函數釋放內存(正如Dirk所說的,我們不能在沒有關於函數的更多信息的情況下多說這些)。

如果真的必須在調用之前進行分配,它應該是這樣看:

[DllImport("yourfile.dll", CharSet = CharSet.Ansi)] 
public static extern sbyte service_GetParameter (String parameter, Int32 length, ref IntPtr val); 

public static string ServiceGetParameter(string parameter, int maxLength) 
{ 
    string ret = null; 
    IntPtr buf = Marshal.AllocCoTaskMem(maxLength+1); 
    try 
    { 
     Marshal.WriteByte(buf, maxLength, 0); //Ensure there will be a null byte after call 
     IntPtr buf2 = buf; 
     service_GetParameter(parameter, maxLength, ref buf2); 
     System.Diagnostics.Debug.Assert(buf == buf2, "The C++ function modified the pointer, it wasn't supposed to do that!"); 
     ret = Marshal.PtrToStringAnsi(buf); 
    } 
    finally { Marshal.FreeCoTaskMem(buf); } 
    return ret; 
} 
+0

service_GetParameter不分配內存。調用者必須分配內存,調用service_GetParameter並釋放內存(在C++中使用delete []) – LukeT

+0

那麼爲什麼需要一個指針指針? ......好吧,無論如何,如果這樣你可能能夠將參數編組爲StringBuilder,儘管這並不能保證。但至少,使用Marshal類的C#函數包裝調用應該可行(儘管它可能比成功的自動編組更慢)。 – Medinoc

+0

我不知道爲什麼需要一個指針指針。你能幫我解釋一些代碼嗎? – LukeT

0

我的是這樣開始:

[DllImport("yourfile.dll", CharSet = CharSet.Ansi] 
public static extern Int32 service_GetParameter([MarshalAs(UnmanagedType.LPStr)] String szParameter, Int32 value_length, [Out] StringBuilder sbValue); 
+0

當然,如果'service_GetParameter'分配內存則更爲複雜。 – Medinoc

+0

@Medinoc爲什麼?這仍然不是C++方法的責任嗎?這只是一個電話。 StringBuilder的使用確保了複製的值,而不是對任何原始內存的引用。 – DonBoitnott

+0

通過「分配內存」,我的意思是「返回一個指向調用者負責釋放的分配內存的指針」。如果是這種情況,C#代碼將泄漏所述內存。如果這不是(例如,它返回一個指向公共緩衝區內的指針,這是其他代碼的責任),那麼沒有問題。 – Medinoc