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 - 编组字符串的主要内容,如果未能解决你的问题,请参考以下文章

将字符串从 c# 编组到 c++

从 C++ dll 编组导出的字符串向量

创建要在 C# 中编组的 C++ Dll 的最佳实践 [关闭]

C#编组(C#调用C++ DLL)

C++ 到 C# 回调结构编组

从 c# dll 调用/编组字符串到非托管代码