C# 和 C++ dll - 编组字符串
Posted
技术标签:
【中文标题】C# 和 C++ dll - 编组字符串【英文标题】:C# and C++ dll - marshalling strings 【发布时间】:2020-05-17 00:23:04 【问题描述】:我制作了一个测试应用程序,将 C# 字符串传递给 C++ DLL 以返回其更改后的值。
来自 MSDN 的示例:
Marshaling Data with Platform Invoke
Strings Sample
部分类用于定义DllImport
:
public class LibWrap
[DllImport(
"PInvokeLib.dll",
EntryPoint = "TestStringAsResult",
ExactSpelling = true,
CharSet = CharSet.Ansi,
SetLastError = true)]
public static extern string TestStringAsResult(string value);
DLL 函数调用:
const string s = "My string !!!";
var str = LibWrap.TestStringAsResult(s);
Console.WriteLine(Environment.NewLine + "String returned: 0", str);
// String returned: My string !!!AAA or String returned: My string !!!+counter value
在 DLL 代码中,我将处理字符串并返回其更改后的值:
// int counter = 0;
PINVOKELIB_API char* TestStringAsResult(char* value)
const size_t alloc_size = 64;
const auto result = static_cast<char*>(CoTaskMemAlloc(alloc_size));
// counter++;
std::string work_str = value;
work_str += "AAA";
//work_str += std::to_string(counter);
StringCchCopyA(result, alloc_size, const_cast<char*>(work_str.c_str()));
return result;
然后我循环了 10 次,例如在 C# 代码中:
const string s = "My string !!!";
var str = LibWrap.TestStringAsResult(s);
Console.WriteLine(Environment.NewLine + "String returned: 0", str);
并得到了从"My string !!! 1"
到"My string !!! 10"
的结果
这表明 DLL 是静态加载到 C# 应用程序进程中的 - 我理解正确吗?
原来在 DLL 中内存被分配了 10 次以获得结果?
我是否需要使用CoTaskMemFree()
?如果需要 - 我如何在 C# 端调用它?
【问题讨论】:
【参考方案1】:在亚当·内森 (Adam Nathan) 书中找到了答案.NET and COM: The Complete Interoperability Guide
第18章第791页
朋友给了我this link
另一种需要使用 IntPtr 的情况发生在函数 分配内存并期望调用者释放内存。这是 在 Win32 API 中相当少见,因为大多数操作都是在调用者分配的 缓冲区(如使用 StringBuilder 的示例中)。当一个 PInvoke 签名返回一个字符串(通过返回类型或通过引用 参数),Interop Marshaler 在内部复制 将非托管字符串转换为 .NET 字符串,然后调用 CoTaskMemFree( 非托管等价的 Marshal.FreeCoTaskMem) 来释放非托管 字符串。但是,如果非托管字符串不是 用 CoTaskMemAlloc 分配!
【讨论】:
以上是关于C# 和 C++ dll - 编组字符串的主要内容,如果未能解决你的问题,请参考以下文章