سؤال

I have not seen the answer on StackOverflow yet. This is in a C# library project with the interfaces defined below (and project settings) so it is visible as a COM component.

The goal is to make the functions/methods in the interop lines visible through the COM interface. The interop lines provide visibility to the functions in an older C library/dll.

The problem is shown through the interop line for Convert in the NativeCalls class below. It includes "static extern". If these (i.e. "static extern") are included in the interface section that is above the class definition (as shown), I get the errors:

  • The modifier 'extern' is not valid for this item
  • The modifier 'static' is not valid for this item

If I remove "extern static", "Convert" as in the interface section will not be found in the class.

How can I decorate the "Convert" line in the interface section so I do not need to write additional methods within the NativeCalls class to wrap every single interop line (i.e. those starting with "public static extern" such as that for "Convert". If I need to do this, I have hundreds to wrap - maybe a nice macro program is in order :). What is a better/shorter way? Thanks for any help.

[ComVisible(true)]
[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83D")]
  public interface IComNativeCallsInterface
{
    [DispId(1)]
    static extern int Convert(ref formatfile fptr); // leaving "static extern" on front causes errors. Removing "static extern" will cause the call "Convert" to not be found in the class.
}

[Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA7D"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IComNativeCallsEventsInterface
{
}

[ComVisible(true)]
[Guid("0D53A3E8-E51A-49C7-944E-E72A2064F93D"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(IComNativeCallsEventsInterface))]
public class NativeCalls : IComNativeCallsInterface
{
    /// Return Type: int
    ///fptr: formatfile*
    [System.Runtime.InteropServices.DllImportAttribute("coldlib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Convert")]
    public static extern int Convert(ref formatfile fptr);

... }

هل كانت مفيدة؟

المحلول

An interface method cannot be static or extern. It doesn't make any sense. In COM in particular, an interface always requires a class instance obtained from IClassFactory::CreateInstance(), etc. That's just the way COM works. In C# in turn, a static method cannot be an implementation of an interface method, even if it has the right parameters and name, for the same reason: a C# interface reference is obtained from casting an object (instance) reference to the interface.

And it makes total sense! Remember that underlying every interface method call there is a hidden (By C++ and C#) this argument that references the object instance. The method signatures don't really match, even if it looks that way on the surface.

If you need to expose the same method both as a COM method and as a plain C external symbol, you will need two copies of the method declaration: the static extern one which implements the functionality, and a second copy that forwards the call, which is declared as public int IComNativeCallsInterface.Convert(ref formatfile fptr). If I remember correctly (I don't have a computer with VS at hand), by declaring the second method as an explicit interface implementation you will be able to have the two declarations match name and formal arguments exactly without a conflict.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top