在经过大量搜索并拼凑出不同的部分解决方案后,我想出了如何做到这一点.
首先,您需要为要尝试访问的对象定义COM coclass:
[ComImport, Guid("..."), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ISomeCOMInterface
{
// Define interface methods here, using PInvoke conversion between types
}
Run Code Online (Sandbox Code Playgroud)
接下来,您需要实例化COM对象.有几种方法可以做到这一点.由于我对DirectSound感兴趣,我用过:
[DllImport("dsound.dll", EntryPoint = "DirectSoundCreate", ...]
static extern void DirectSoundCreate(IntPtr GUID, [Out, MarshalAs(UnmanagedType.Interface)] out IDirectSound directSound, IntPtr pUnkOuter);
IDirectSound directSound;
DirectSoundCreate(IntPtr.Zero, out directSound, IntPtr.Zero);
Run Code Online (Sandbox Code Playgroud)
因为我现在有了COM对象,所以我可以使用Hans的建议Marshal.GetComInterfaceForObject():
IntPtr comPtr = Marshal.GetComInterfaceForObject(directSound, typeof(IDirectSound));
IntPtr vTable = Marshal.ReadIntPtr(comPtr);
Run Code Online (Sandbox Code Playgroud)
作为额外的奖励,您可以像这样迭代vtable函数:
int start = Marshal.GetStartComSlot(typeof(IDirectSound));
int end = Marshal.GetEndComSlot(typeof(IDirectSound));
ComMemberType mType = 0;
for (int i = start; i <= end; i++)
{
System.Reflection.MemberInfo mi = Marshal.GetMethodInfoForComSlot(typeof(IDirectSound), i, ref mType);
Console.WriteLine("Method {0} at address 0x{1:X}", mi.Name, Marshal.ReadIntPtr(vTable, i * Marshal.SizeOf(typeof(IntPtr))).ToInt64());
}
Run Code Online (Sandbox Code Playgroud)
额外阅读/参考:
| 归档时间: |
|
| 查看次数: |
1907 次 |
| 最近记录: |