views:

312

answers:

2

Hello,

I am trying to create a class that implements the IUnknown interface. I have the following code in the header file.

#pragma once

#include "stdafx.h"
#include "Unknwn.h"


class Vmr9Presenter : IVMRImagePresenter9, IVMRSurfaceAllocator9
{
public:
Vmr9Presenter(void);
HRESULT Initialize(void);
~Vmr9Presenter(void);
STDMETHODIMP QueryInterface(const IID &riid, void **ppvObject);
};

I have included the relevant uuid.lib and several others. However, when I attempt to compile, I get the error

Error 2 error LNK2001: unresolved external symbol "public: virtual long __stdcall Vmr9Presenter::QueryInterface(struct _GUID const &,void * *)" (?QueryInterface@Vmr9Presenter@@UAGJABU_GUID@@PAPAX@Z) Vmr9Presenter.obj VmrPresenter

This leads me to believe that something isn't getting pulled in. Any suggestions on how to get rid of this error?

Thanks

A: 

Do either of IVMRImagePresenter9, IVMRSurfaceAllocator9 already implement IUnknown? Maybe you need:

class Vmr9Presenter : IVMRImagePresenter9, IVMRSurfaceAllocator9, IUnknown

I would guess you may also need to implement AddRef() and Release() too according to the docs for IUnknown.

BrianLy
Based off your comment, if either does implement IUnknown, could I just do a reinterpret_cast<IUnknown*>(this) and call queryInterface?
Alex
As Larry stated you need to create an implementation of the functions exposed on each interface. You then need to tell it which IUnknown to use.
BrianLy
+4  A: 

All the I* interfaces are just that - interface definitions. An interface is a pure virtual base class in C++ terms.

When you say:

class Vmr9Presenter : IVMRImagePresenter9, IVMRSurfaceAllocator9

you're saying "the Vmr9Presenter class implements these interfaces". You're also saying "The Vmr9Presenter class derives from two pure virtual base classes named IVMRImagePresenter9 and IVMRSurfaceAllocator9. By convention all interfaces derive from a pure virtual base class called IUnknown.

This means that you need to implement all the methods in the pure virtual base classes in your object. So you need to implement all the methods on IVMRImagePresenter9 and IVMRSurfaceAllocator9. You ALSO need to implement all the methods on their base classes, including IUnknown.

IUnknown has 3 methods: AddRef, Release and QueryInterface. The error you're reporting says that the linker was unable to find a function named Vmr9Presenter::QueryInterface.

You need to add such a function to your class, once you do that it should work.

Typically a QI implementation looks like:

HRESULT IVmr9Presenter::QueryInterface(REFIID iid, PVOID *pvInterface)
{
    if (pvInterface == NULL)
    {
        return E_POINTER;
    }
    *pvInterface = NULL;
    if (iid == IID_IUnknown)
    {
         *pvInterface = static_cast<PVOID>(static_cast<IUnknown *>(this));
         return S_OK;
    }
    if (iid == IID_IVMRSurfaceAllocator9)
    {
         *pvInterface = static_cast<PVOID>(static_cast<IVMRSurfaceAllocator9*>(this));
         return S_OK;
    }
         :
    else
    {
        return E_NOINTERFACE;
    }
}
Larry Osterman
Your explanation makes perfect sense. However, in the code you posted, the static_cast<IUnknown *>(this) is flagged by the compiler as an ambiguous reference.I'm assuming this is because both IVMRSurfaceAllocator9 and IVMRImagePresenter9 derive from IUnknown? This cast appears to work however.static_cast<PVOID>(static_cast<IUnknown*>(static_cast<IVMRSurfaceAllocator9*>(this)))I'm assuming this is because the compiler cannot, on its own, choose which implementation of IUnknown to use? Or am I completely off base and this won't do what I think it does?
Alex
You're totally right, I was being lazy. Sorry 'bout that. Your solution is exactly right.
Larry Osterman