如何传递一个可以从本机写入到 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);
}
在我的托管程序中,我的字符串看起来很好,但在非托管方面它变成了垃圾。我没有复制所有代码,但我认为这说明了我想要完成的任务。如果我以错误的方式处理这件事或者犯了错误,请告诉我。谢谢。
I'm trying to get a string from my managed code into my unmanaged code:
unmanaged 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;
}
managed 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);
}
Within my managed program my string looks fine but it turns into garbage on the unmanaged side. I didn't copy all the code but I think this makes the point of what I'm trying to accomplish. If I'm going about this the wrong way or I made mistakes, please let me know. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
试试这个:
Try this:
我遇到了这个问题,试图将字符串从 C# 返回到 C。我遇到了很多死胡同,但是 Olivier Levrey 在 codeproject 建议使用
IntPtr
来完成此操作。该解决方案对我来说非常有效。目前您有这个委托声明:
立即想到的是,
value
实际上应该是一个out
参数,就像IDictionary<,>.TryGetValue(键,输出值)
。将其赤裸裸地声明为字符串值
不会提供任何语义机会返回实际值!正如 @dtb 所建议的,通常提供的一种选择是使用StringBuilder
。对我来说,我得到的结果正是你得到的——返回到 C 端的字符串是官方的。但奥利维尔的解决方案奏效了。修改您的委托以使用
IntPtr
作为value
:value
表示我们可以为其分配值的非托管字符串。实现这一目标的实际步骤有点混乱,但最终还是有效的。假设您有一些想要返回到 C 端的字符串
s
,这是您需要实现的代码,以便将其内容传输到IntPtr
value
:完成此操作后,您的返回值已被复制到由
value
命名的内存缓冲区中。I ran into this exact issue, trying to return a string from C# to C. I ran into a lot of dead-ends, but Olivier Levrey on codeproject suggested the use of
IntPtr
to accomplish this. The solution worked great for me.Currently you have this delegate declaration:
Immediately what comes to mind is that really,
value
should be anout
parameter, like forIDictionary<,>.TryGetValue(key, out value)
. For it to be declared nakedly asstring value
does not provide any semantic opportunity to return the actual value! As @dtb suggests, one option often afforded is to use aStringBuilder
. For me, I got exactly the result you got -- the string returned to the C side was gobbledygook. But Olivier's solution worked.Modify your delegate to use an
IntPtr
forvalue
:value
represents an unmanaged string to which we can assign a value. The actual steps to achieve this is a bit of a mess, but it works in the end.Assuming you have some string
s
that you want to return to the C side, this is the code you need to implement in order to transport its contents into theIntPtr
value
:Once this is done, your return value has been copied into the memory buffer named by
value
.