views:

187

answers:

3

Hello, I would like to pass a COM method as a function argument but I get this error (Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86):

error C3867: 'IDispatch::GetTypeInfoCount': function call missing argument list; use '&IDispatch::GetTypeInfoCount' to create a pointer to member

What am I missing?

Thank you very much.

#include <atlbase.h>

void update( HRESULT(*com_uint_getter)(UINT*), UINT& u )
{
   UINT tmp;
   if ( S_OK == com_uint_getter( &tmp ) ) {
      u = tmp;
   }
}

// only for compile purpose, it will not work at runtime
int main(int, char*[])
{
   // I choose IDispatch::GetTypeInfoCount just for the sake of exemplification
   CComPtr< IDispatch > ptr;
   UINT u;
   update( ptr->GetTypeInfoCount, u );
   return 0;
}
+2  A: 

Looks like a straight c++ problem.

Your method expects a pointer to a function.

You have a member function - (which is different from a function).

Typically you will need to either:
1. Change the function that you want to pass to being static.
2. Change the type of pointer expected to a member function pointer.

The syntax for dealing with member function pointers is not the best...

A standard trick would be (1) and then pass the object this pointer explicitly as an argument allowing you to then call non static members.

morechilli
Thank you, I will study http://www.parashift.com/c++-faq-lite/pointers-to-members.html
uvts_cvs
+1  A: 

Boost.Function is also a reasonable choice here (note that I didn't test what I've written below, so it might require some modification - particularly, I'm not sure if you have to call some kind of get() method on your CComPtr object):

#include <atlbase.h>
#include <boost/function.hpp>
#include <boost/bind.hpp>

void update( boost::function<HRESULT (UINT*)> com_uint_getter, UINT& u )
{
   UINT tmp;
   if ( S_OK == com_uint_getter( &tmp ) ) {
      u = tmp;
   }
}

// only for compile purpose, it will not work at runtime
int main(int, char*[])
{
   // I choose IDispatch::GetTypeInfoCount just for the sake of exemplification
   CComPtr< IDispatch > ptr;
   UINT u;
   update( boost::bind(&IDispatch::GetTypeInfoCount, ptr), u );
   return 0;
}

This is the same as all that pointer-to-member stuff that morechilli mentioned, but it hides some of the messier syntax of using it.

Joel
uvts_cvs
A: 

As morechilli pointed out this is a C++ issue. Here it is the solution, thanks to my colleague Daniele:

#include <atlbase.h>

template < typename interface_t >
void update( interface_t* p, HRESULT (__stdcall interface_t::*com_uint_getter)(UINT*), UINT& u )
{
   UINT tmp;
   if ( S_OK == (p->*com_uint_getter)( &tmp ) ) {
      u = tmp;
   }
}

// only for compile purpose, it will not work at runtime
int main(int, char*[])
{
   // I choose IDispatch::GetTypeInfoCount just for the sake of exemplification
   CComPtr< IDispatch > ptr;
   UINT u;
   update( ptr.p, &IDispatch::GetTypeInfoCount, u );
   return 0;
}
uvts_cvs