[Mono-list] Mono Embedding: manage events

Robert Jordan robertj at gmx.net
Wed Apr 2 05:53:04 EDT 2008


Ing. Francesco Carsana wrote:
>> The recommended way is to declare the handlers as icalls in
>> managed code:
> 
> The problem is that I can't modify .NET assembly source code.
> I only know that assembly has this event:

You don't need to modify the original assembly. Implement the
wrapper in a new assembly.

> In my C++ wrapper class to this assembly, I have to find a way
> to pass a function pointer (or something else) to the assembly in
> order to manage that event. Is it possible?

No.

> Is there another way to do that?

No.

> Could someone please give me an example, please?


Untested. Implement this in its own assembly:

public class ConnectionEventWrapper
{
	[MethodImpl (MethodImplOptions.InternalCall)]
	public static extern void UnmanagedHandler (string n, bool c);

	public static void AttachEvent(Session source)
	{
		source.OnConnectionEvent +=
			new ConnectionEventHandler (UnmanagedHandler);
	}

	public static void DetachEvent(Session source)
	{
		source.OnConnectionEvent -=
			new ConnectionEventHandler (UnmanagedHandler);
	}
}


C++:

// this must be called once
mono_add_internal_call ("ConnectionEventWrapper::UnmanagedHandler",
	&icall_ConnectionEventWrapper_UnmanagedHandler);

void
icall_ConnectionEventWrapper_UnmanagedHandler (MonoString n,
	MonoBoolean c)
{
	// do something
}



Hooking the event:


void
ConnectionEventWrapper_AttachEvent (MonoObject* session)
{
	static MonoAssembly *assembly = NULL;
	static MonoClass *class = NULL;
	static MonoMethod *attach_event_method = NULL;

	MonoObject *exception;
	gpointer args[2];

	// load wrapper assembly
	if (!assembly) {
		MonoImageOpenStatus status;

		// "wrapper.dll" is the name of the assembly
		// implementing the wrapper.
		assembly = mono_assembly_open ("wrapper.dll", &status);

		g_assert (assembly);
	}

	// load class ConnectionEventWrapper
	if (!class) {
		class = mono_class_from_name (
			mono_assembly_get_image (assembly),
			"yournamespace", "ConnectionEventWrapper");

		g_assert (wrapper_class);
	}

	// load method ConnectionEventWrapper::AttachEvent
	if (!attach_event_method) {
		attach_event_method = mono_class_get_method_from_name (
			class, "AttachEvent", 1);

		g_assert (attach_event_method);
	}


	// call AttachEvent(session);
	args [0] = session;
	mono_runtime_invoke (attach_event_method, NULL,
		args, &exception);

	if (exception) {
		// handle exception
	}
}


Robert



More information about the Mono-list mailing list