问题
I am trying to call GetImageDlg
on IWiaDevMgr2
. There are a number of quite complicated methods (which I am not using) referencing a number of types (that I am also not using). As I cannot find a TLB or an IDL from which to automatically generate my ComImport
, I would prefer to avoid having to manually translate all of the referenced types.
Can I "skip" methods and types by substituting from
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2
{
IEnumWIA_DEV_INFO EnumDeviceInfo(
int lFlags);
IWiaItem2 CreateDevice(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID);
// ...snip five other method declarations...
IWiaItem2 GetImageDlg(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
IntPtr IntPtrParent,
[MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
[MarshalAs(UnmanagedType.BStr)] string bstrFilename,
/* [out] */ out int plNumFiles,
/* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);
};
to
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
void VTablePlaceholder0();
void VTablePlaceholder1();
void VTablePlaceholder2();
void VTablePlaceholder3();
void VTablePlaceholder4();
void VTablePlaceholder5();
void VTablePlaceholder6();
[return: MarshalAs(UnmanagedType.Interface)]
object GetImageDlg(
int lFlags,
[MarshalAs(UnmanagedType.BStr)] string bstrDeviceID,
IntPtr IntPtrParent,
[MarshalAs(UnmanagedType.BStr)] string bstrFolderName,
[MarshalAs(UnmanagedType.BStr)] string bstrFilename,
/* [out] */ out int plNumFiles,
/* [size_is][size_is][out] */ [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5, ArraySubType = UnmanagedType.BStr)] out string[] ppbstrFilePaths);
};
Everything seems to work fine, and as long as I don't call any of the placeholders. Can I do this without consequences?
回答1:
Sure you can do this. You're the only one who will be using this interface definition, so that's fine.
Of course, if this interface was used as a callback from native to managed, it would be a problem, but in this case you would be implementing it somehow. Implementing such dummy methods is a sign of future problems.
Note there's an official way of doing it. You can use a special _VtblGap{0}_{1}
name for the placeholder, where 0 is an index, and 1 is the number of methods you want to skip.
See the implementation in Roslyn here (it's also in the Common Language Infrastructure specification): https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReader/ModuleExtensions.cs
// From IMetaDataEmit::DefineMethod documentation (http://msdn.microsoft.com/en-us/library/ms230861(VS.100).aspx)
// ----------------------
// In the case where one or more slots need to be skipped, such as to preserve parity with a COM interface layout,
// a dummy method is defined to take up the slot or slots in the v-table; set the dwMethodFlags to the mdRTSpecialName
// value of the CorMethodAttr enumeration and specify the name as:
//
// _VtblGap<SequenceNumber><_CountOfSlots>
//
// where SequenceNumber is the sequence number of the method and CountOfSlots is the number of slots to skip in the v-table.
// If CountOfSlots is omitted, 1 is assumed.
// ----------------------
//
// From "Partition II Metadata.doc"
// ----------------------
// For COM Interop, an additional class of method names are permitted:
// _VtblGap<SequenceNumber><_CountOfSlots>
// where <SequenceNumber> and <CountOfSlots> are decimal numbers
// ----------------------
So in your case, it would be:
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("79C07CF1-CBDD-41ee-8EC3-F00080CADA7A")]
public interface IWiaDevMgr2_Fake
{
void _VtblGap1_7(); // skip seven methods
...
};
来源:https://stackoverflow.com/questions/47564635/can-i-simplify-method-signatures-i-am-not-using-in-a-comimport