C++/CLI:#pragma 托管/非托管范围

nev*_*ind 5 .net clr pinvoke mixed-mode c++-cli

我有一个混合模式 DLL,其中有一个包含托管和非托管代码的 .cpp 文件。一个简化的重现示例如下所示:

#include "stdafx.h"
#pragma managed // Just for explicitness (doesn't influence results)
#include <msclr\marshal.h>

void Test()
{
    System::String^ sName = "";
    msclr::interop::marshal_context context;
    context.marshal_as<const TCHAR*>(sName);
}

//#pragma unmanaged // uncomment this line to get errors
Run Code Online (Sandbox Code Playgroud)

此代码编译成功,但是如果我取消注释最后一行 ( #pragma unmanaged),则会产生以下错误:

2>  Test.cpp
2>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\msclr\marshal.h(48): error C3280: 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler' : a member-function of a managed type cannot be compiled as an unmanaged function
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>          This diagnostic occurred in the compiler generated function 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler(void)'
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\msclr\marshal.h(48): error C3642: 'System::Object::Object(void)' : cannot call a function with __clrcall calling convention from native code
2>          This diagnostic occurred in the compiler generated function 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler(void)'
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\msclr\marshal.h(48): error C3175: 'System::Object::Object' : cannot call a method of a managed type from unmanaged function 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler'
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>          This diagnostic occurred in the compiler generated function 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler(void)'
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\msclr\marshal.h(48): error C3821: 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler(void)': managed type or function cannot be used in an unmanaged function
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>          This diagnostic occurred in the compiler generated function 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler(void)'
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\msclr\marshal.h(282): error C3645: 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler' : __clrcall cannot be used on functions compiled to native code
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
2>          This diagnostic occurred in the compiler generated function 'msclr::interop::marshal_context::internal_marshaler<_To_Type,_From_Type,_Needs_Context>::internal_marshaler(void)'
2>          with
2>          [
2>              _To_Type=const wchar_t *,
2>              _From_Type=System::String ^,
2>              _Needs_Context=true
2>          ]
Run Code Online (Sandbox Code Playgroud)

#pragma managed我发现可以通过在 .cpp 文件末尾添加来消除该错误。但我仍然不明白为什么会出现错误。这种行为#pragma unmanaged对我来说似乎完全违反直觉。有人可以解释一下吗?

据我所理解:

  • #pragma (un)managed影响其下面的代码编译。因此,如果它是在 .cpp 文件末尾定义的(下面没有任何内容),则它不应该有任何效果。
  • http://msdn.microsoft.com/en-us/library/0adb9zxe.aspx说:

    实例化模板函数时,模板定义时的编译指示状态决定它是托管的还是非托管的。

marshal_contexttemplate 是在包含的文件中定义的marshal.h,并且应该被编译为托管(因为它在前一行有显式的 #pragma),而不管文件底部的 #pragma 是什么。

我有什么地方说错了吗?