2011-12-08 45 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的内存缓冲区中。

相关问题