2012-02-13 56 views
0

爲什麼會拋出InvalidProgramException?我見過的不同變種紛紛表示:爲什麼原生返回類型拋出System.InvalidProgramException?

  1. JIT遇到了內部限制。

  2. 公共語言運行時檢測到無效的程序。

我已經簡化的例子到最低限度的,我可以的情況下重現該問題。你應該能夠獲取下面的代碼並將其粘貼到VS2010中以重現此操作。

下面的基本結構是CppReferenceTest是一個CLR DLL程序集,它包含一個返回本地結構的方法。裁判是一個試圖調用此方法的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; 
} 

回答

3

在.NET中,類型標識包括類型是從加載組件。因此,您不應將#include用於受管引用,只能使用#import(項目設置中的「參考」選項卡相當於#import)。

現在發生的事情是,通過#include -ing頭文件,你保證在當前程序集中有一個_NativeStruct類型。您的main函數使用此類型。

然後,在運行時,CLR發現Class1::GetNativeEnum()返回了一個不同的_NativeStruct類型,在CppReferenceTest.dll中定義。這些類型不兼容,你會得到例外。

只需使用您參考的程序集的元數據中提供的類型即可。


除此之外,不要在C++中做typedef struct _NativeStruct NativeStruct。這不是必要的,它會消除錯誤信息,更糟糕的是,它與保留的標識符衝突。

+0

感謝您的迴應。如果我刪除了'#include',我得到一個編譯錯誤'錯誤C2065:'NativeStruct':未聲明的標識符'。我如何獲得對該本地結構的引用?我還注意到,如果我將簽名更改爲'Class1 :: GetNativeEnum([Out] NativeStruct&ns)'它可以工作 - 可能是由於兩個本機類型的等效內存佈局? – Bringer128 2012-02-14 01:19:41

+0

感謝您對'typedef'部分的評論。結構匹配我正在接口的C結構,因此我儘可能地將示例保持爲接近實際問題。 – Bringer128 2012-02-14 01:25:50

+0

@ Bringer128:這有點奇怪。如果你在客戶端使用'#pragma make_public',它會有幫助嗎? – 2012-02-14 01:40:21