将字符串从非托管 c++ dll 返回到 c#

Returning a string from an unmanaged c++ dll to c#

我正在尝试从 C# 调用非托管 C++,但收到有关 return 值的异常。 异常:

System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot marshal 'return value': Invalid managed/unmanaged type combination (Arrays can only be marshaled as LPArray, ByValArray, or SafeArray).'

我有一个类似的功能,在没有 return 值(无效)的情况下看起来是一样的,但没有任何问题。

我将 c++ 项目的平台(编译器)设置为 v100(Visual Studio 2010)并在 c# 项目中使用 .net 4.5。

C++ 项目创建了一个 lib+dll 文件,我将它们都放在可执行文件夹中。

当我尝试在 C# 代码中将 return 值替换为 "String" 时,异常转换为:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

当我删除 return 值函数 属性 ([return: MarshalAs(UnmanagedType.BStr)]) 时,我收到以下异常:

System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot marshal 'return value': Invalid managed/unmanaged type combination.'

当我执行以下组合时:删除 return 值函数 属性 并将 return 类型转换为字符串,应用程序将自行关闭而不会捕获任何异常。

C++代码

extern "C"
{
    ExternalDll_API char* FuncA(char* projectId);
}

ExternalDll_API char* FuncA(char* projectId)
{
    return "abc";
}

C#代码

[DllImport("ExternalDll.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
public static extern char[] FuncA(string projectId);

var key = FuncA(projectId.ToString());

要从 C++ dll 接收空终止字符串,您可以这样做:

1-将 return 类型更改为 IntPtr:

[DllImport("ExternalDll.dll")]
public static extern IntPtr FuncA(string projectId);

2-使用 Marshal 从指针中检索字符串:

var result = FuncA(someString);
var strResult = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(result);