为什么本机返回类型会抛出System.InvalidProgramException?

时间:2012-02-13 07:48:43

标签: .net interop c++-cli

为什么会抛出InvalidProgramException?我见过的不同变种说:

  
      
  1. JIT遇到内部限制。

  2.   
  3. Common Language Runtime检测到无效程序。

  4.   

我已经将示例简化为可以重现该问题的最小环境。您应该能够获取以下代码并将其粘贴到VS2010中以重现这一点。

下面的基本结构是CppReferenceTest是一个CLR DLL程序集,它包含一个返回本机结构的方法。 Referee是一个试图调用此方法的CLR控制台应用程序。裁判有一个项目参考CppReferenceTest。

我从其他测试中得知,调用CppReferenceTest内部的方法不会抛出InvalidProgramException。我也知道如果我更改方法签名以获取引用参数而不是返回值,则不会抛出任何异常。

程序集1 - CppReferenceTest(CLR dll库)

文件:NativeHeader.h

#pragma managed(push, off)

typedef struct _NativeStruct {
    int val1;
    int val2;
} NativeStruct;   

#pragma managed(pop)

文件:CppReferenceTest.h

#pragma once

#include "NativeHeader.h"

using namespace System;

#pragma make_public(_NativeStruct)

namespace CppReferenceTest {

public ref class Class1
{
    public:
        static NativeStruct GetNativeEnum();
    };
}

文件:CppReferenceTest.cpp

#include "stdafx.h"

#include "CppReferenceTest.h"

using namespace CppReferenceTest;

NativeStruct Class1::GetNativeEnum()
{
    NativeStruct ns = {1, 2};
    return ns;
}

程序集2 - 裁判(CLR控制台应用程序)

文件:Referee.cpp

#include "stdafx.h"

#include "NativeHeader.h"

using namespace System;
using namespace CppReferenceTest;

int main(array<System::String ^> ^args)
{
    NativeStruct ns = Class1::GetNativeEnum();
    Console::WriteLine(L"Hello World");
    return 0;
}

1 个答案:

答案 0 :(得分:3)

在.NET中,类型标识包括从中加载类型的程序集。因此,您不应将#include与托管引用一起使用,仅#import(“项目设置”中的“引用”选项卡等同于#import)。

现在发生的事情是,通过#include - 头文件,您保证当前程序集中有_NativeStruct类型。您的main函数使用此类型。

然后,在运行时,CLR发现Class1::GetNativeEnum()返回_NativeStruct中定义的其他CppReferenceTest.dll类型。这些类型不兼容,您将获得例外。

只需使用您引用的程序集的元数据中提供的类型。


除此之外,不要在C ++中使用typedef struct _NativeStruct NativeStruct。没有必要,它会搞错误消息,更糟糕的是,它与保留的标识符冲突。