C#和C++ dll--------------Marshalling字符串

问题描述 投票:1回答:1

我做了一个测试应用程序,将一个C#字符串传递给一个C++ DLL,以返回它的变化值。

例子取自MSDN。

用平台调用来处理数据

弦乐样品

定义类的一部分 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#端调用它?

c# c++ marshalling
1个回答
0
投票

在Adam Nathan的书中找到了答案 .NET and COM: The Complete Interoperability Guide 第18章第791页

朋友给我 这个环节

另一种需要使用IntPtr的情况发生在函数分配内存并期望调用者释放内存的时候。这在Win32 API中是相当罕见的,因为大多数的操作都是在调用者分配的缓冲区上进行的(就像在使用StringBuilder的例子中一样)。当PInvoke签名返回一个字符串时(无论是通过返回类型还是通过引用参数),Interop Marshaler会在内部将未管理字符串的内容复制到一个.NET字符串中。然后调用CoTaskMemFree(相当于Marshal.FreeCoTaskMem的非管理型)来释放非管理型字符串。. 然而,如果未管理的字符串没有用 CoTaskMemAlloc!

© www.soinside.com 2019 - 2024. All rights reserved.