2011-12-08 40 views
2

我想從我的託管代碼得到一個字符串到我的非託管代碼:我怎樣才能傳遞一個空字符串緩衝區,可以從本地寫入到C#?

非託管的DLL:

typedef int (__stdcall * GetNameFromDictionaryCallback)(ULONGLONG id, WCHAR * name); 

declspec(dllexport) void __stdcall UnmanagedSetNameLookupCallback(GetNameFromDictionaryCallback fn) 
{ 
    GetNameFromDictionaryCallback GetNameFromDictionary = fn; 

    WCHAR * value = new WCHAR[256]; 
    ULONGLONG key = 0x250000000DA44785; 
    GetNameFromDictionary(key, value); // reverse P/Invoke call to C# function 
    wprintf_s("%ls", value); // just to display the result for simplicity 
    delete value; 
} 

管理DLL:

public class ProgramInterop 
{ 
    private delegate int GetNameFromDictionaryCallback(UInt64 key, string value); 
    private static GetNameFromDictionaryCallback mGetNameInstance; 
    private Dictionary<UInt64, string> dict; 

    private ProgramInterop() 
    { 
     mGetNameInstance = new GetNameFromDictionaryCallback(GetNameFromDictionary); 
     UnmanagedSetNameLookupCallback(mGetNameInstance); 
    } 

    public bool GetNameFromDictionary(UInt64 key, string value) 
    { 
     return dict.TryGetValue(key, out value); 
    } 

    [DllImport("Unmanaged.dll")] 
    private static extern void UnmanagedSetNameLookupCallback(GetNameFromDictionaryCallback fn); 
} 

在我的管理程序我的字符串看起來很好,但它變成非託管方的垃圾。我沒有複製所有的代碼,但我認爲這是我想要完成的。如果我以錯誤的方式去解決這個問題,或者我犯了錯誤,請告訴我。謝謝。

+0

如果您可以更改回調以使用'BSTR',則可以在此問題中使用該解決方案:http://stackoverflow.com/questions/4455234/passing-string-from-c-to-c-sharp – shf301

回答

0

試試這個:

delegate int GetNameFromDictionaryCallback(
    UInt64 key, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder value); 

public bool GetNameFromDictionary(UInt64 key, StringBuilder value) 
{ 
    string s; 
    if (dict.TryGetValue(key, out s)) 
    { 
     value.Append(s); 
     return true; 
    } 
    return false; 
} 
+0

我在非託管方獲得中文字,但託管方看起來應該如此。我錯過了一些進出還是在這裏參考? – Scleractinian

+0

這比沒有好:-)不幸的是,我真的不能做任何事情,只能在黑暗中刺傷。答案已更新。 – dtb

+0

這是我最需要做的事情,也是爲此感謝的最接近的答案。我會繼續嘗試不同的方式將這些符號轉換爲他們應該的。我認爲你可以從託管中得到一個返回字符串值,但它似乎大多數示例和問題,我已經發現傳遞字符串非託管,但調用來自託管,而我從非託管調用來從託管獲得字符串返回值,但沒有什麼大不了的。我會改變我的方案來做不同的事情。 – Scleractinian

0

ran into this exact issue,試圖返回從C#到C字符串我遇到了很多死角,但奧利弗Levrey on codeproject建議選用IntPtr做到這一點。該解決方案對我很好。

目前你有這樣的委託聲明:

private delegate int GetNameFromDictionaryCallback(UInt64 key, string value); 

立即想到什麼是真的,value應該是一個out參數,像IDictionary<,>.TryGetValue(key, out value)。因爲string value沒有提供任何語義機會,所以返回實際值!正如@dtb所暗示的,通常提供的一種選擇是使用StringBuilder。對我來說,我得到了你得到的結果 - 返回到C方的字符串是gobbledygook。但奧利維爾的解決方案工作。

修改您的代理使用的IntPtrvalue

private delegate int GetNameFromDictionaryCallback(UInt64 key, IntPtr value); 

value表示非託管字符串,我們可以分配一個值。實現這一目標的實際步驟有點混亂,但最終還是有效的。

假設你有一些字符串s要返回到C面,這是你需要爲了實現其內容傳輸到IntPtrvalue代碼:

// Convert from managed to unmanaged string and store in `sPtr` 
IntPtr sPtr = Marshal.StringToHGlobalAnsi(s); 
// Create a byte array to receive the bytes of the unmanaged string (including null terminator) 
var sBytes = new byte[s.Length + 1]; 
// Copy the the bytes in the unmanaged string into the byte array 
Marshal.Copy(sPtr, sBytes, 0, s.Length); 
// Copy the bytes from the byte array into the buffer 
Marshal.Copy(sBytes, 0, buffer, sBytes.Length); 
// Free the unmanaged string 
Marshal.FreeHGlobal(sPtr); 

一旦做到這一點,您的返回值已被複制到名爲value的內存緩衝區中。

相關問題