2011-05-19 138 views
2

我有一個問題,我試着去看幾乎所有的海報解決方案,但找不到合適的解決方案。DllImport,Char *&和StringBuilder C/C#

這個問題很簡單,希望從託管C#中的非託管C代碼返回字符串。 C函數是:

extern "C" __declspec(dllexport) int process_batch (char *&result); 

,並在C#我進口DLL:

[DllImport("mydll.dll")] 
public static extern IntPtr process_batch(StringBuilder result); 

我跑,但在我的StringBuilder的返回值是無感7-8字符串! (我認爲內存地址)

我試着在StringBuilder之前添加ref,這次我在StringBuilder中得到了正確的返回值,但是我得到了AccessViolationException: 試圖讀取或寫入受保護的內存。這通常表明其他內存已損壞。

所以我需要你的幫助來解決這個問題。

還有一件事,我用c中的malloc來分配內存給char *變量。

感謝,

回答

3

如果您確實想要這樣做,請將該參數作爲ref IntPtr傳遞,然後撥打Marshal.PtrToStringAnsi或類似名稱。

[DllImport("mydll.dll")] 
public static extern IntPtr process_batch(ref IntPtr result); 

需要注意的是,因爲你分配在C malloc字符串時,.NET程序必須跟蹤返回的指針,以便它可以通過它回到你被釋放。否則你會有內存泄漏。

如果您要通過ref StringBuilder,您將無法取消分配C程序分配的內存。

而且,有人在另一篇評論說,你需要設置調用約定:

[DllImport("mydll.dll", CallingConvention=CallingConvention.Cdecl)] 
+0

非常感謝。我用它,它的工作。 – Amin 2011-05-19 20:55:36

1

我一直在使用下面的代碼成功:

[DllImport("user32.dll", EntryPoint = "GetClassName", ExactSpelling = false, 
      CharSet = CharSet.Auto, SetLastError = true)] 
private static extern int _GetClassName(IntPtr hwnd, StringBuilder lpClassName, 
      int nMaxCount); 

public static string GetClassName(IntPtr hWnd) 
{ 
    StringBuilder title = new StringBuilder(MAXTITLE); 
    int titleLength = _GetClassName(hWnd, title, title.Capacity + 1); 
    title.Length = titleLength; 

    return title.ToString(); 
} 

我建議對進口的方法通過DllImportAttribute更具體的聲明。嘗試CharSet = CharSet.Auto位,例如

我知道這與您的原始問題並不完全相關,因爲這使用Windows API,但也許它有幫助。

+0

我還要聲明調用約定。我看到的大多數處理p/Invoke的問題都與調用約定有關。 – 2011-05-19 19:02:14

+0

@Rhhound:極好的一點!在這種情況下,它應該是'Cdecl'-對嗎? – yas4891 2011-05-19 19:06:12