【发布时间】:2018-03-08 12:34:48
【问题描述】:
我正在尝试从 c# 调用非托管 c++,但收到有关返回值的异常。 例外:
System.Runtime.InteropServices.MarshalDirectiveException: 'Cannot marshal 'return value': 无效的托管/非托管类型组合(数组只能作为 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: 'Cannot marshal 'return value': 无效的托管/非托管类型组合。'
当我做以下组合:删除返回值函数属性并将返回类型转换为字符串时,应用程序会自行关闭而不会捕获任何异常。
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-知道返回字符串的大小,2-传递一个 StringBuilder 并从 C++ 代码中填充它,而不是直接返回一个 char 指针.
标签: c# c++ com marshalling