Help with Invocation of C Method

  • Thread starter Thread starter Tyler
  • Start date Start date
T

Tyler

Can someone help by explaining why the following class will not compile
(VS2005), and what can be done to pass the function pointer to the "C"
method?

When I compile the following program, I get "error C2664: 'CMethod' : cannot
convert parameter 1 from 'Test::DoItFn ^' to 'void (__cdecl *)(void *)':

#include "stdafx.h"

void CMethod(void (* pfvFunPointer)(void *), void * pfvValue)
{
(*pfvFunPointer)(pfvValue);
return;
}

ref class Test
{
public:
delegate void DoItFn(void * pfvValue);

virtual void DoIt(void * pfvValue)
{
return;
}

virtual void Run()
{
DoItFn ^ tvfnDoIt = gcnew DoItFn(this, &Test::DoIt);
CMethod(tvfnDoIt, nullptr);
return;
}
};

Can someone please help? Any good documentation references would also be
appreciated.

Thanks, Tyler
 
Hi Tyler,
Thanks for Willy's reply!

I just wanted to check how things are going and whether Willy's suggestion
is useful for you. If there is any question, please feel free to join the
community and we are here to support you at your convenience. Thanks for
your understanding!

Best Regards,

Terry Fei[MSFT]
Microsoft Community Support
Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)



--------------------
 
Thanks Willy,

The link was a lot of help. I have still one problem though that I hope
someone can help with. When I take the example and modify the callback
function to have a parameter, I get unexplained behaviour where my managed
callback function is invoked 2x's. I think this has to do with the calling
convention (if I add __stdcall to the ANSWERCB typedef line, the problem
goes awa), but I'm not sure what I should really do (is there a better
answer, something that makes more sense?) to fix the problem.

Can someone help - I have included modified test below. When I run it, the
GetNumber method is invoked 2x's - once when expected, and once after
execution returns to the main() immediately after having executed the first
TakesCallback() method.

Thanks, Tyler
---------------------------------

// MarshalDelegate2.cpp
// compile with: /clr
#include "stdafx.h"
#include <iostream>

using namespace System;
using namespace System::Runtime::InteropServices;

#pragma unmanaged
typedef int (/* __stdcall */ *ANSWERCB)(void *);
static ANSWERCB cb;

int TakesCallback(ANSWERCB fp, void * fpValue) {
cb = fp;
if (cb) {
printf_s("[unmanaged] got callback address (%d), calling it...\n",
cb);
return cb(fpValue);
}
printf_s("[unmanaged] unregistering callback");
return 0;
}
#pragma managed

public delegate int GetTheAnswerDelegate(void *);

int GetNumber(void * fpValue) {
Console::WriteLine("[managed] callback!");
static int x = 0;
return ++x;
}

static GCHandle gch;

int main() {
GetTheAnswerDelegate^ fp = gcnew GetTheAnswerDelegate(GetNumber);

gch = GCHandle::Alloc(fp);

IntPtr ip = Marshal::GetFunctionPointerForDelegate(fp);
ANSWERCB cb = static_cast<ANSWERCB>(ip.ToPointer());
Console::WriteLine("[managed] sending delegate as callback...");

int answer = TakesCallback(cb, 0);

// possibly much later (in another function)...

Console::WriteLine("[managed] releasing callback mechanisms...");
TakesCallback(0, 0);
gch.Free();
}
 
Back
Top