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

时间:2017-09-27 06:23:57

标签: c# c++ com marshalling

我正在尝试从c#调用非托管c ++,但收到有关返回值的异常。 例外:

  

System.Runtime.InteropServices.MarshalDirectiveException:'无法封送'返回值':无效的托管/非托管类型组合(数组只能封送为LPArray,ByValArray或SafeArray)。'

我有一个看起来相同的函数,没有返回值(void),没有任何问题。

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

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

当我尝试在c#代码中将返回值替换为“String”时,异常转换为:

  

System.AccessViolationException:'尝试读取或写入受保护的内存。这通常表明其他内存已损坏。'

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

  

System.Runtime.InteropServices.MarshalDirectiveException:'无法封送'返回值':无效的托管/非托管类型组合。'

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

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());

1 个答案:

答案 0 :(得分:4)

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

1 - 将返回类型更改为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);