Click here to Skip to main content
Click here to Skip to main content

Tagged as

Wrapping a C++ callback in a .NET System::Action

, 17 Nov 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Wrapping a C++ callback in a .NET Action so you can use the .NET Task Parallel Library
Here's a template class for wrapping a C++ callback in an action. This is so you can queue up tasks in C++ using the .NET Task Parallel Library.
// This class bridges a C++ callback to a .NET Action, which
// can be queued up in a .NET Task.
template<typename T1, typename T2>
ref class CallbackToAction
{
public:
  typedef void (CallbackHandler)(T1, T2);
 
  // Converts function pointer and parameters to an action. Note that
  // the arguments need to be either pointers, values types, or managed pointers.
  // You cannot pass objects by value.
  static System::Action^ Convert(CallbackHandler* handler, T1 arg1, T2 arg2)
  {
    CallbackToAction<T1,T2>^ callbackToAction = gcnew CallbackToAction<T1,T2>();
    callbackToAction->_handler = handler;
    callbackToAction->_arg1 = arg1;
    callbackToAction->_arg2 = arg2;
    return callbackToAction->ToAction();
  }
 
private:
 
  void DoCallback()
  {
    _handler(_arg1, _arg2);
  }
 
  System::Action^ ToAction()
  {
    return gcnew Action(this, &CallbackToAction::DoCallback);
  }
 
  CallbackHandler* _handler;
  T1 _arg1;
  T2 _arg2;
};
Here's a whole console app that shows you how to use it:
 
#include "CallbackToAction.h"
using namespace System;
using namespace System::Threading;
using namespace System::Threading::Tasks;
 
class MyClass
{
  int _sleepTime;
public:
  MyClass(int sleepTime)
  {
    _sleepTime = sleepTime;
  }
 
  void DoSomething()
  {
    Thread::Sleep(_sleepTime);
  }
};
 
typedef CallbackToAction<MyClass*, Barrier^> MyCallbackToAction;
 
void CallbackFunction(MyClass* myObject, Barrier^ barrier)
{
  myObject->DoSomething();
  Console::WriteLine(L"A task has finished");
  barrier->RemoveParticipant();
}
 
int main(array<System::String ^> ^args)
{
  Barrier^ barrier = gcnew Barrier(3);
  Console::WriteLine(L"Queing 2 tasks");
  MyClass myObject1(1000);
  MyClass myObject2(3000);
  Task::Factory->StartNew(MyCallbackToAction::Convert(&CallbackFunction, &myObject1, barrier));
  Task::Factory->StartNew(MyCallbackToAction::Convert(&CallbackFunction, &myObject2, barrier));
 
  Console::WriteLine(L"Waiting");
  barrier->SignalAndWait();
  Console::WriteLine(L"All Finished. Press Enter");
  Console::ReadLine();
 
  return 0;
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

John Stewien
Founder Cheesy Design
Taiwan Taiwan
John graduated from the University of South Australia in 1997 with a Bachelor of Electronic Engineering Degree, and since then he has worked on hardware and software in many fields including Aerospace, Defence, and Medical giving him over 10 of years experience in C++ and C# programming. In 2009 John Started his own contracting company doing business between Taiwan and Australia.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 17 Nov 2011
Article Copyright 2011 by John Stewien
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid