Вопрос

My IDL:

[
    object,
    uuid(52D64BCC-03F1-442B-BED1-70992111E2B1),
    helpstring("ISimpleObject Interface"),
    pointer_default(unique)
]
interface ISimpleObject : IUnknown{
    [helpstring("method Hoop"), local] HRESULT Hoop(void);
};
[
    uuid(3D9ABD55-3C84-43C8-9C34-3915B6B34989),
    version(1.0),
    helpstring("ComServer 1.0 Type Library")
]
library ComServerLib
{
    importlib("stdole2.tlb");
    [
        uuid(42E2236D-1DA0-455F-9EF4-31A4A1E04F47),
        helpstring("SimpleObject Class")
    ]
    coclass SimpleObject
    {
        [default] interface ISimpleObject;
    };
};

My COM class:

class ATL_NO_VTABLE CSimpleObject :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CSimpleObject, &CLSID_SimpleObject>,
    public ISimpleObject
{
public:
    CSimpleObject()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLEOBJECT)

BEGIN_COM_MAP(CSimpleObject)
    COM_INTERFACE_ENTRY(ISimpleObject)
END_COM_MAP()

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }

public:
    // ISimpleObject
    STDMETHOD(Hoop)(void)
    {
        return S_OK;
    }
};

OBJECT_ENTRY_AUTO(__uuidof(SimpleObject), CSimpleObject)

My .NET client:

[ComImport]
[Guid("52D64BCC-03F1-442B-BED1-70992111E2B1")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ISimpleObject
{
    [PreserveSig]
    int Hoop();
}

[ComImport]
[Guid("42E2236D-1DA0-455F-9EF4-31A4A1E04F47")]
public class SimpleObject
{
}

class Program
{
    static void Main(string[] args)
    {
        SimpleObject simpleObject = new SimpleObject();

        ISimpleObject simpleObjectInterface = (ISimpleObject)simpleObject;

        int returnValue = simpleObjectInterface.Hoop(); // Error!
    }
}

The client gets exception "System.AccessViolationException: Attempted to read or write protected memory...". Why?

I'm using Visual Studio 2008, Windows Vista x64. C++ and C# projects have x86 configuration.

Это было полезно?

Решение

int Hoop();

is an incorrect translation of the IDL declaration into C#. The correct one would be

void Hoop();

.NET wraps COM result codes (HRESULT) into correspondent C# exceptions. For example if you return E_NOTIMPL in C++ code, .NET runtime will throw an instance of the NotImplementedException class

*UPDATE*

According, to MSDN, the main application thread is initialized to 'MTA' by default. Your object CSimpleObject is configured to reside in the 'STA'. In order to make cross-apartament calls, the COM runtime will use your implementation of the proxy/stub to marshall the corresponding data.

The runtime needs a valid proxy/stub implementation which is generated by MIDL from your IDL file.

You have marked the 'Hoop' function as "Local". This means that MIDL will not generate any marshalling code for this method, that is why you get an exception.

One should remove the 'local' attribute since it is designed to be used only inside the server where an object is implemented. But as a possible solution I may suggest you to use the object from a thread configured to run in STA. Anyway, this is a bad approach, since it doesn't guarantees, that no marshalling will be involved.

You may mark your main thread to run in STA as follows:

[STAThread()]
static void Main(string[] args)
{
    ...
}

I hope this will help you to solve the problem.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top