【问题标题】:Returning a string from an unmanaged c++ dll to c# [duplicate]将字符串从非托管 c++ dll 返回到 c# [重复]
【发布时间】: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


【解决方案1】:

要从 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 2013-01-07
    相关资源
    最近更新 更多