.net - 解决错误 C3821 : managed type or function cannot be used in an unmanaged function

标签 .net windows c++-cli interop

我正在编写一个 C++/CLI 层来处理一些互操作。

native API 填充涉及固定数组、联合、匿名结构等的复杂结构:

typedef struct DECLSPEC_ALIGN(16) _FOO {
    union {
        BAR Bar;
        struct {
           POP   Array[8];
           DWORD More;
        };
    };
} FOO, *PFOO;

我正在尝试将此数据结构转换为更“合理”的 .NET 类,以供 C# 使用。问题是,我不能在同一个函数中使用这个遗留结构和 gcnew 我的新类:

Foo^ Test::GetFoo(HANDLE h)
{
    FOO foo;                              // Necessarily unmanaged

    if (!::GetFoo(h, &foo))
        throw gcnew Exception("GetFoo failed");

    Foo^ result = gcnew Foo();            // Necessarily managed

    // populate result

    return result;
}

这样做会产生错误:

Error 2 error C3821: 'void Test::GetFoo(HANDLE)': managed type or function cannot be used in an unmanaged function

如果 native 结构和 gcnew 不能存在于同一个函数中,那么人们怎么可能希望(甚至手动)在两者之间编码数据?

这里的许多问答涉及包装非托管类,这在这里似乎无关紧要。

最佳答案

Aligned data types not supported in managed code

这才是真正的错误信息,不幸的是它没有出现在错误列表窗口中。您只能在“输出”窗口中看到它。当编译器错误消息看起来很奇怪时要记住一些事情。

是的,它是准确的,托管代码不会在堆栈对齐保证的情况下运行,而堆栈对齐保证是对齐此结构所需的。 32 位代码以 4 对齐运行,64 位代码可以提供 8。不足以获得 16。编译器对此也无能为力,通常的堆栈指针操作在 IL 中不可用,这搞砸了抖动生成的元数据告诉垃圾收集器在遍历堆栈时在哪里查找对象引用。

所以,没办法,你不能让它成为局部变量。您有多种选择,最直接的方法是分配它:

#include <malloc.h>
....

    FOO* value = (FOO*)_aligned_malloc(sizeof(FOO), __alignof(FOO));
    try {
        // etc...
    }
    finally {
        _aligned_free(value);
    }

关于.net - 解决错误 C3821 : managed type or function cannot be used in an unmanaged function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24355263/

相关文章:

c# - Visual Studio : C++\CLI wrapper assembly path dependency problems

c# - 即使不使用 RedirectStandardError/RedirectStandardOutput,Process.WaitForExit 也会挂起

c# - 具有从非泛型基类继承的泛型类的 MongoDB C# 驱动程序类型鉴别器

c# - 如何使用 C# 编写和播放音乐?

c# - IReflect 和 DispId

windows - 安全更新

templates - 基本类型在 C++ 和 CLI 之间传递模板参数

.net - ElasticSearch 2.0 带最小起订量的嵌套单元测试

C++ 进程检查

windows - perl中的无缓冲IO