C# 和 C++ dll - 编组字符串
C# and C++ dll - marshalling strings
我制作了一个测试应用程序,将 C# 字符串传递给 C++ DLL 以 return 其更改后的值。
取自 MSDN 的示例:
Marshaling Data with Platform Invoke
用于定义 DllImport
的 class 的一部分:
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 代码中,我将使用字符串和 return 其更改后的值:
// 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# 端调用它?
在 Adam Nathan 的书中找到了答案
.NET and COM: The Complete Interoperability Guide
第 18 章第 791 页
朋友给了我this link
Another case that requires the use of IntPtr occurs when a function
allocates memory and expects the caller to free the memory. This is
fairly rare in Win32 APIs, because most operate on a caller-allocated
buffer (as in the examples that use StringBuilder). When a PInvoke
signature returns a string (either via a return type or a by-reference
parameter), the Interop Marshaler internally copies the contents of
the unmanaged string to a .NET string, then calls CoTaskMemFree (the
unmanaged equivalent of Marshal.FreeCoTaskMem) to free the unmanaged
string. This is a problem, however, if the unmanaged string was not
allocated with CoTaskMemAlloc!
我制作了一个测试应用程序,将 C# 字符串传递给 C++ DLL 以 return 其更改后的值。
取自 MSDN 的示例:
Marshaling Data with Platform Invoke
用于定义 DllImport
的 class 的一部分:
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 代码中,我将使用字符串和 return 其更改后的值:
// 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# 端调用它?
在 Adam Nathan 的书中找到了答案
.NET and COM: The Complete Interoperability Guide
第 18 章第 791 页
朋友给了我this link
Another case that requires the use of IntPtr occurs when a function allocates memory and expects the caller to free the memory. This is fairly rare in Win32 APIs, because most operate on a caller-allocated buffer (as in the examples that use StringBuilder). When a PInvoke signature returns a string (either via a return type or a by-reference parameter), the Interop Marshaler internally copies the contents of the unmanaged string to a .NET string, then calls CoTaskMemFree (the unmanaged equivalent of Marshal.FreeCoTaskMem) to free the unmanaged string. This is a problem, however, if the unmanaged string was not allocated with CoTaskMemAlloc!