Search code examples
c#c++com

How to use ComImport?


I am learning com and to use it in .net based application.

I created a simple MathFunction dll which has one function Add 2 numbers.

Then I used ComImport to load it in windows form application. Everything worked fine without error. When I run the application the result I got was zero for adding 2 numbers.

I passed 2 arguments to the function.

IMathFunc mathFunc = GetMathFunc();
int res = mathFunc.Add(10, 20);

Now for this I got the result as 0. Here IMathFunc is the interface of type IUnkown.

[ComImport]
    [Guid("b473195c-5832-4c19-922b-a1703a0da098")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IMathFunc
    {
        int Add(int a, int b);
        void ThrowError();
    }

When I debug it for the function

int Add(int a,int b)

it shows some bignumber in "a" and 10 for "b".

Debug Image

THis is my mathFunction Library

#include<windows.h>
using namespace System;

static const GUID IID_MathFunc =
{ 0xb473195c, 0x5832, 0x4c19, { 0x92, 0x2b, 0xa1, 0x70, 0x3a, 0xd, 0xa0, 0x98 } };

struct IMathFunc:public IUnknown
{
    virtual int Add(int a, int b) = 0;

    STDMETHOD(ThrowError)() = 0;
};

namespace MathFuncLibrary {

    class MathFunc: public IMathFunc
    {
        volatile long refcount_;
    public:

        MathFunc();

        int Add(int a, int b);
        STDMETHODIMP_(ULONG) Release();

        STDMETHODIMP_(ULONG) AddRef();
        STDMETHODIMP  QueryInterface(REFIID guid, void **pObj);

        STDMETHODIMP ThrowError();

    };

}

int MathFunc::Add(int a, int b)
{
    return a + b;
}

STDMETHODIMP_(ULONG) MathFunc::Release()
{
    ULONG result = InterlockedDecrement(&refcount_);
    if(result==0)delete this;
    return result;
}

STDMETHODIMP MathFunc::QueryInterface(REFIID guid, void **pObj)
{
    if (pObj == NULL) {
        return E_POINTER;
    }
    else if (guid == IID_IUnknown) {
        *pObj = this;
        AddRef();
        return S_OK;
    }
    else if (guid == IID_MathFunc) {
        *pObj = this;
        AddRef();
        return S_OK;
    }
    else {
        // always set [out] parameter
        *pObj = NULL;
        return E_NOINTERFACE;
    }
}

STDMETHODIMP_(ULONG) MathFunc::AddRef()
{
    return InterlockedIncrement(&refcount_);
}

STDMETHODIMP MathFunc::ThrowError()
{
    return E_FAIL;
}

MathFunc::MathFunc() :refcount_(1)
{

}



extern "C" __declspec(dllexport) LPUNKNOWN __stdcall GetMathFunc()
{
    return new MathFunc();
}

Am I missing anything that resulted in this error or I did whole-thing wrong..?


Solution

  • I got it with the suggestion from Hans Passant.

    You need to change the method

    virtual int Add(int a, int b) = 0;
    

    to

    virtual STDMETHOD_(UINT32,Add)(int a, int b) = 0;
    

    And then in ComImport interface

    int Add(int a, int b);
    

    to

     [PreserveSig]int Add(int a,int b);