471,071 Members | 899 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,071 software developers and data experts.

Interoperabiliy of boost::signals and managed event receivers

Hello all.

I've got a bunch of existing, non managed, C++ DLLs that export types
with, among other things, public events implemented using the
boost::signals library.

Now, I need to have these DLL interoperate with managed code. Among
others things, the managed code need to be able to register for
notification with the boost signals. I've tried different approaches
(trying to register a pinned delegate with the boost::signal, etc...),
but the only thing I could make to work is the ugly code below :

///Unmanaged DLL, compiled without /clr
///file event_source_lib.h
#ifdef EVENT_SOURCE_LIB_EXPORTS
#define EVENT_SOURCE_LIB_API __declspec(dllexport)
#else
#define EVENT_SOURCE_LIB_API __declspec(dllimport)
#endif

#include <boost/signals.hpp>

// This class is exported from the event_source_lib.dll
class EVENT_SOURCE_LIB_API EventSource {
public:
boost::signal<void (int)> event;
void RaiseEvent();

};

///Unmanaged DLL, compiled without /clr
///file event_source_lib.cpp
#include "event_source_lib.h"
void EventSource::RaiseEvent()
{
event(3);
}
///managed C++ console app
///file event_sink.cpp
#include "event_source_lib.h"
#include <boost/bind.hpp>
#include <vcclr.h>
#using <mscorlib.dll>

using namespace System;

__gc class EventSink
{
public:
void Sink(int a);
};

void EventSink::Sink(int a)
{
System::Console::WriteLine(S"In managed handler");
}
static void ManagedHandler(gcroot<EventSink*> instance, int a)
{
instance->Sink(a);
}

#pragma unmanaged
static void UnmanagedHandler(gcroot<EventSink*> instance, int a)
{
ManagedHandler(instance, a);
}
//If I do this directly in the _tmain funcion (managed code), I've got
an SEH exception at runtime.
static boost::signals::connection RegisterEventSink(EventSource&
source, gcroot<EventSink*> instance)
{
return source.event.connect(boost::bind(&UnmanagedHandler ,
instance, _1));
}

#pragma managed

int _tmain()
{
EventSource source;
EventSink* sink=new EventSink;
boost::signals::connection con=RegisterEventSink(source,
gcroot<EventSink*>(sink)); //(1)
source.RaiseEvent();
con.disconnect();
return 0;
}
This solution requires *3* static functions (2 unmanaged and 1
managed) to be able to register a member funcion of a __gc class with
the boost signal. My real librarie has tens of different signals, with
different signatures, and the managed wrapper code would soon be an
horrible mess of macros hack if I use this technique.

A curiosity about this code : If I do not declare the unmanaged
RegisterEventSink and call boost::signal::connect directly from
_tmain, I've got an SEHException at runtime. However, if I declare
RegisterEventSink *but do not call it*, the code run smooth. The line
(1) can therefore be replaced with:
boost::signals::connection
con=source.event.connect(boost::bind(&UnmanagedHan dler,
gcroot<EventSink*>(sink), _1));
I suspect that the boost::bind specialization is (correctly) build
when compiling RegisterEventSink, and the same specialization is used
in _tmain. But if RegisterEventSink is commented out, the compiler is
unable to compile the bind specialization when in a managed context.

Does anyone have another cleaner solution for this problem?
Thanks.

Arnaud
MVP - VC
Nov 17 '05 #1
0 1745

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

16 posts views Thread by Jeff Flinn | last post: by
reply views Thread by Russell Hind | last post: by
reply views Thread by Arnaud Debaene | last post: by
9 posts views Thread by atomik.fungus | last post: by
1 post views Thread by Noah Roberts | last post: by
2 posts views Thread by timor.super | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.