none
C# 的 COM 交互  RRS feed

  • 问题

  • 请问什么时候使用:

    什么时候使用MarshalAs ,什么时候不使用,MSDN的示例程序有的地方使用MarshalAs有的地方不使用此关键字

    [In] 
    [In, MarshalAs(UnmanagedType.BStr)] 
    [return: MarshalAs(UnmanagedType.Interface)] 

    另外UnmanagedType枚举中有很多,请问那些是用在哪呢?目前我知道BStr是对应于System.String

    其他的呢?

    	// 将 IMediaControl 声明为一个从 IDispatch 接口派生的 
    	// COM 接口:
    	[Guid("56A868B1-0AD4-11CE-B03A-0020AF0BA770"),InterfaceType(ComInterfaceType.InterfaceIsDual)] 
    	interface IMediaControl   // 此处不能列出任何基接口
    	{ 
    		// 注意 IUnknown 接口成员未在此处列出:
    
    		void Run();
    
    		void Pause();
    
    		void Stop();
    
    		void GetState( [In] int msTimeout, [Out] out int pfs);
    
    		void RenderFile(
    			[In, MarshalAs(UnmanagedType.BStr)] string strFilename);
    
    		void AddSourceFilter( 
    			[In, MarshalAs(UnmanagedType.BStr)] string strFilename, 
    			[Out, MarshalAs(UnmanagedType.Interface)] out object ppUnk);
    
    		[return: MarshalAs(UnmanagedType.Interface)] 
    		object FilterCollection();
    
    		[return: MarshalAs(UnmanagedType.Interface)] 
    		object RegFilterCollection();
                
    		void StopWhenReady(); 
    	}

    2014年3月24日 6:46

答案

  • 你好:

    欢迎来到MSDN中文论坛。

    大部分情况下CLR都知道如何去封送数据,默认的数据封送行为基本上满足正常需要,只有在需要封送的数据出现歧义的时候才需要通过MarshalAs特性来指定目标数据类型。比如在托管代码中的string类型,在非托管语言中有很多种不同的形式,BStr,LPStr,LPTStr等,这时候CLR默认将字符串参数封送为BStr类型传递给COM方法,如果你想指定封送成LPStr类型,那么就需要添加这个MarshalAs(LPStr)特性。

    有关于MarshalAsAttribute的更多内容请参考MSDN文档,其中有很不错的说明:

    MarshalAsAttribute 类

    可将该特性应用于参数、字段或返回值。

    该特性为可选特性,因为每个数据类型都有默认的封送处理行为。仅在可以将给定类型封送到多个类型时需要此特性。  LPStr, a LPWStr, a LPTStr, or a BStr.例如,可将字符串作为 LPStrLPWStrLPTStrBStr 封送到非托管代码. 默认情况下,公共语言运行时将字符串参数作为 BStr 封送到 COM 方法。可将 MarshalAsAttribute 特性应用于个别的字段或参数,使该字符串作为 LPStr 而不是 BStr 进行封送. Tlbexp.exe(类型库导出程序)   将封送处理首选项传递给公共语言运行时。当用于 COM 互操作或平台调用时,某些参数和返回值将具有不同的默认封送处理行为。默认情况下,运行时将字符串参数(以及值类型中的字段)作为 LPStr 封送到平台调用方法或函数。有关更多信息,请参见默认封送处理行为. 大多数情况下,该特性只是使用 UnmanagedType 枚举标识非托管数据的格式,如下面的 C# 签名所示:

    void
        MyMethod([MarshalAs(LPStr)] String s);
    

    某些 UnmanagedType 枚举成员需要附加信息。例如,当 UnmanagedTypeLPArray 时需要附加信息。有关如何将此特性用于数组的完整说明,请参见 数组的默认封送处理Tlbimp.exe(类型库导入程序)   还将此特性应用于参数、字段及返回值,以指示输入类型库中的数据类型不是相应托管数据类型的默认类型, 为清楚起见,Tlbimp.exe 始终将 MarshalAsAttribute 应用于 StringObject 类型,而不管在输入类型库中指定的是何种类型。


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.



    2014年3月25日 7:19
    版主

全部回复

  • 你好:

    欢迎来到MSDN中文论坛。

    大部分情况下CLR都知道如何去封送数据,默认的数据封送行为基本上满足正常需要,只有在需要封送的数据出现歧义的时候才需要通过MarshalAs特性来指定目标数据类型。比如在托管代码中的string类型,在非托管语言中有很多种不同的形式,BStr,LPStr,LPTStr等,这时候CLR默认将字符串参数封送为BStr类型传递给COM方法,如果你想指定封送成LPStr类型,那么就需要添加这个MarshalAs(LPStr)特性。

    有关于MarshalAsAttribute的更多内容请参考MSDN文档,其中有很不错的说明:

    MarshalAsAttribute 类

    可将该特性应用于参数、字段或返回值。

    该特性为可选特性,因为每个数据类型都有默认的封送处理行为。仅在可以将给定类型封送到多个类型时需要此特性。  LPStr, a LPWStr, a LPTStr, or a BStr.例如,可将字符串作为 LPStrLPWStrLPTStrBStr 封送到非托管代码. 默认情况下,公共语言运行时将字符串参数作为 BStr 封送到 COM 方法。可将 MarshalAsAttribute 特性应用于个别的字段或参数,使该字符串作为 LPStr 而不是 BStr 进行封送. Tlbexp.exe(类型库导出程序)   将封送处理首选项传递给公共语言运行时。当用于 COM 互操作或平台调用时,某些参数和返回值将具有不同的默认封送处理行为。默认情况下,运行时将字符串参数(以及值类型中的字段)作为 LPStr 封送到平台调用方法或函数。有关更多信息,请参见默认封送处理行为. 大多数情况下,该特性只是使用 UnmanagedType 枚举标识非托管数据的格式,如下面的 C# 签名所示:

    void
        MyMethod([MarshalAs(LPStr)] String s);
    

    某些 UnmanagedType 枚举成员需要附加信息。例如,当 UnmanagedTypeLPArray 时需要附加信息。有关如何将此特性用于数组的完整说明,请参见 数组的默认封送处理Tlbimp.exe(类型库导入程序)   还将此特性应用于参数、字段及返回值,以指示输入类型库中的数据类型不是相应托管数据类型的默认类型, 为清楚起见,Tlbimp.exe 始终将 MarshalAsAttribute 应用于 StringObject 类型,而不管在输入类型库中指定的是何种类型。


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.



    2014年3月25日 7:19
    版主
  • 感谢,版主
    2014年3月25日 7:33