C#如何调用原生C++ COM对象详解
什么是COM对象
COM(Component Object Model)是一种微软开发的组件对象模型,用于实现不同程序间的互操作性,特别是OLE(Object Linking and Embedding)。
如何调用原生C++ COM对象
使用C#语言调用原生C++ COM对象需要引用InteropServices命名空间和ComImport特性。
using System.Runtime.InteropServices;
[ComImport]
[Guid("<CLSID>")]
public class MyCOMObject
{
//在此可以定义接口的方法
}
上面的代码中,使用了C#的ComImport特性,该特性表示当前类将被用作Interop中的COM对象,并且使用C++的GUID(Globally Unique Identifier)指定了COM对象的类标识符(CLSID,Class IDentifier)。
接下来,可以依照COM对象的接口来定义相应的方法:
[ComImport]
[Guid("<IID>")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMyCOMObject
{
//在此可以定义COM对象的方法
}
上面的代码中,使用了C#的InterfaceType特性和IMyCOMObject接口,该接口使用C++的GUID指定了COM对象的接口标识符(IID,Interface IDentifier),并且指定了COM对象的接口类型为IUnknown。
最后,使用COM对象需要使用COM接口调用,这可以使用System.Runtime.InteropServices.Marshal类来实现:
MyCOMObject obj = (MyCOMObject)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("<CLSID>")));
IMyCOMObject comObj = (IMyCOMObject)obj;
//调用COM对象的方法
comObj.MethodName();
上面的代码中,首先使用Activator类创建了MyCOMObject对象,然后通过将MyCOMObject对象强制类型转换为IMyCOMObject接口,将COM对象转换为COM接口,最后即可调用COM接口的方法。
示例
下面以调用Windows API的GetModuleHandle作为示例,说明如何使用C#调用原生C++ COM对象。
示例一:使用DllImport
首先,可以使用C#的DllImport特性直接声明Windows API的GetModuleHandle方法。
using System.Runtime.InteropServices;
public class Program
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr GetModuleHandle(string lpModuleName);
public static void Main(string[] args)
{
IntPtr hMod = GetModuleHandle(null);
Console.WriteLine(hMod);
}
}
上面的代码中,使用了C#的DllImport特性,该特性表示当前的方法将调用原生C++ COM对象。
示例二:使用COM接口
接下来,可以使用COM接口调用Windows API的GetModuleHandle方法。
using System;
using System.Runtime.InteropServices;
[ComImport]
[Guid("00000000-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IUnknown
{
}
[ComImport]
[Guid("79EAC9EE-BAF9-11CE-8C82-00AA004BA90B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IProvideClassInfo
{
[PreserveSig]
int GetClassInfo([MarshalAs(UnmanagedType.Interface)] out ITypeInfo ppTI);
}
[ComImport]
[Guid("83E91E85-82C1-492F-9034-7B03BFFABA35")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITest
{
uintptr_t GetModuleHandle([MarshalAs(UnmanagedType.LPWStr)] string lpModuleName);
}
public class Program
{
static void Main(string[] args)
{
Type comType = Type.GetTypeFromProgID("Kernel32");
object comObj = Activator.CreateInstance(comType);
IProvideClassInfo classInfo = (IProvideClassInfo)comObj;
ITypeInfo typeInfo;
classInfo.GetClassInfo(out typeInfo);
IntPtr hMod = (IntPtr)((ITest)comObj).GetModuleHandle(null);
Console.WriteLine(hMod);
}
}
上面的代码中,定义了Windows API的GetModuleHandle方法的COM接口ITest,同时使用Activator类创建了Kernel32 COM对象,并通过Type.GetTypeFromProgID方法获得了COM对象的类型信息。然后通过将COM对象强制类型转换为IProvideClassInfo和ITest两个COM接口,最后可以调用Windows API的GetModuleHandle方法。
总结
这里提供了两种调用原生C++ COM对象的方式,开发者可以选择适合自己的方式进行开发。需要注意的是,使用COM接口进行调用需要根据COM对象提供的接口来定义相应的COM接口。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#如何调用原生C++ COM对象详解 - Python技术站