Added signal support.

This commit is contained in:
Owen Fraser-Green 2004-03-26 15:25:59 +00:00
parent 7dd5704023
commit 45277e93d8
10 changed files with 552 additions and 114 deletions

View file

@ -42,6 +42,11 @@ namespace DBus
SetupWithMain();
}
public void Flush()
{
dbus_connection_flush(RawConnection);
}
public void SetupWithMain()
{
dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);

45
mono/ErrorMessage.cs Normal file
View file

@ -0,0 +1,45 @@
namespace DBus
{
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
public class ErrorMessage : Message
{
public ErrorMessage() : base(MessageType.Error)
{
}
internal ErrorMessage(IntPtr rawMessage, Service service) : base(rawMessage, service)
{
}
public ErrorMessage(Service service) : base(MessageType.Error, service)
{
}
public new string Name
{
get {
if (this.name == null) {
this.name = Marshal.PtrToStringAnsi(dbus_message_get_error_name(RawMessage));
}
return this.name;
}
set {
if (value != this.name) {
dbus_message_set_error_name(RawMessage, value);
this.name = value;
}
}
}
[DllImport("dbus-1")]
private extern static bool dbus_message_set_error_name(IntPtr rawMessage, string name);
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_get_error_name(IntPtr rawMessage);
}
}

View file

@ -6,6 +6,13 @@ namespace DBus
using System.Reflection;
using System.Collections;
internal enum Result
{
Handled = 0,
NotYetHandled = 1,
NeedMemory = 2
}
internal class Handler
{
private string[] path = null;
@ -15,7 +22,6 @@ namespace DBus
private DBusObjectPathVTable vTable;
private Connection connection;
private Service service;
private DBusHandleMessageFunction filterCalled;
internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
IntPtr userData);
@ -24,18 +30,6 @@ namespace DBus
IntPtr rawMessage,
IntPtr userData);
internal delegate int DBusHandleMessageFunction(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData);
private enum Result
{
Handled = 0,
NotYetHandled = 1,
NeedMemory = 2
}
[StructLayout (LayoutKind.Sequential)]
private struct DBusObjectPathVTable
{
@ -67,8 +61,8 @@ namespace DBus
}
public Handler(object handledObject,
string pathName,
Service service)
string pathName,
Service service)
{
Service = service;
Connection = service.Connection;
@ -88,14 +82,22 @@ namespace DBus
ref vTable,
IntPtr.Zero))
throw new OutOfMemoryException();
// Setup the filter function
this.filterCalled = new DBusHandleMessageFunction(Filter_Called);
if (!dbus_connection_add_filter(Connection.RawConnection,
this.filterCalled,
IntPtr.Zero,
IntPtr.Zero))
throw new OutOfMemoryException();
RegisterSignalHandlers();
}
private void RegisterSignalHandlers()
{
ProxyBuilder proxyBuilder = new ProxyBuilder(Service, HandledObject.GetType(), this.pathName);
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
EventInfo eventE = (EventInfo) signalEntry.Value;
Delegate del = Delegate.CreateDelegate(eventE.EventHandlerType, proxyBuilder.GetSignalProxy(), "Proxy_" + eventE.Name);
eventE.AddEventHandler(HandledObject, del);
}
}
}
public object HandledObject
@ -113,21 +115,6 @@ namespace DBus
this.introspector = Introspector.GetIntrospector(value.GetType());
}
}
public int Filter_Called(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData)
{
Message message = Message.Wrap(rawMessage, Service);
if (message.Type == Message.MessageType.Signal) {
Signal signal = (Signal) message;
} else if (message.Type == Message.MessageType.MethodCall) {
MethodCall methodCall = (MethodCall) message;
}
return (int) Result.NotYetHandled;
}
public void Unregister_Called(IntPtr rawConnection,
IntPtr userData)
@ -143,7 +130,8 @@ namespace DBus
switch (message.Type) {
case Message.MessageType.Signal:
System.Console.WriteLine("FIXME: Signal called.");
// We're not interested in signals here because we're the ones
// that generate them!
break;
case Message.MessageType.MethodCall:
return (int) HandleMethod((MethodCall) message);
@ -216,7 +204,7 @@ namespace DBus
{
this.service = value;
}
}
}
[DllImport ("dbus-1")]
private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string[] path, ref DBusObjectPathVTable vTable, IntPtr userData);
@ -224,11 +212,5 @@ namespace DBus
[DllImport ("dbus-1")]
private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string[] path);
[DllImport ("dbus-1")]
private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
DBusHandleMessageFunction filter,
IntPtr userData,
IntPtr freeData);
}
}

View file

@ -8,7 +8,8 @@ namespace DBus
{
private static Hashtable interfaceProxies = new Hashtable();
private Hashtable methods = null;
private Hashtable signals = null;
private string interfaceName;
private InterfaceProxy(Type type)
@ -17,17 +18,34 @@ namespace DBus
InterfaceAttribute interfaceAttribute = (InterfaceAttribute) attributes[0];
this.interfaceName = interfaceAttribute.InterfaceName;
AddMethods(type);
AddSignals(type);
}
// Add all the events with Signal attributes
private void AddSignals(Type type)
{
this.signals = new Hashtable();
foreach (EventInfo signal in type.GetEvents(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly)) {
object[] attributes = signal.GetCustomAttributes(typeof(SignalAttribute), false);
if (attributes.GetLength(0) > 0) {
MethodInfo invoke = signal.EventHandlerType.GetMethod("Invoke");
signals.Add(signal.Name + " " + GetSignature(invoke), signal);
}
}
}
// Add all the methods with Method attributes
private void AddMethods(Type type)
{
this.methods = new Hashtable();
foreach (MethodInfo method in type.GetMethods(BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly)) {
object[] attributes = method.GetCustomAttributes(typeof(MethodAttribute), true);
object[] attributes = method.GetCustomAttributes(typeof(MethodAttribute), false);
if (attributes.GetLength(0) > 0) {
methods.Add(GetKey(method), method);
methods.Add(method.Name + " " + GetSignature(method), method);
}
}
}
@ -46,16 +64,26 @@ namespace DBus
{
return this.Methods.Contains(key);
}
public bool HasSignal(string key)
{
return this.Signals.Contains(key);
}
public EventInfo GetSignal(string key)
{
return (EventInfo) this.Signals[key];
}
public MethodInfo GetMethod(string key)
{
return (MethodInfo) this.Methods[key];
}
private string GetKey(MethodInfo method)
public static string GetSignature(MethodInfo method)
{
ParameterInfo[] pars = method.GetParameters();
string key = method.Name + " ";
string key = "";
foreach (ParameterInfo par in pars) {
if (!par.IsOut) {
@ -73,6 +101,13 @@ namespace DBus
return this.methods;
}
}
public Hashtable Signals
{
get {
return this.signals;
}
}
public string InterfaceName
{

View file

@ -10,6 +10,7 @@ DBUS_SHARP_FILES= \
Custom.cs \
DBusException.cs \
Error.cs \
ErrorMessage.cs \
Handler.cs \
InterfaceAttribute.cs \
InterfaceProxy.cs \
@ -22,6 +23,7 @@ DBUS_SHARP_FILES= \
Server.cs \
Service.cs \
Signal.cs \
SignalAttribute.cs \
DBusType/IDBusType.cs \
DBusType/Array.cs \
DBusType/Boolean.cs \

View file

@ -80,14 +80,23 @@ namespace DBus
}
// If it doesn't exist then create a new Message around it
Message message = null;
MessageType messageType = (MessageType) dbus_message_get_type(rawMessage);
switch ((MessageType) dbus_message_get_type(rawMessage)) {
switch (messageType) {
case MessageType.Signal:
message = new Signal(rawMessage, service);
break;
case MessageType.MethodCall:
message = new MethodCall(rawMessage, service);
break;
case MessageType.MethodReturn:
message = new MethodReturn(rawMessage, service);
break;
case MessageType.Error:
message = new ErrorMessage(rawMessage, service);
break;
default:
throw new ApplicationException("Unknown message type to wrap: " + messageType);
}
return message;
@ -140,6 +149,8 @@ namespace DBus
{
if (!dbus_connection_send (Service.Connection.RawConnection, RawMessage, ref serial))
throw new OutOfMemoryException ();
Service.Connection.Flush();
}
public void Send()
@ -245,23 +256,19 @@ namespace DBus
protected virtual string Name
{
set
{
if (value != this.name)
{
dbus_message_set_member (RawMessage, value);
this.name = value;
}
set {
if (value != this.name) {
dbus_message_set_member(RawMessage, value);
this.name = value;
}
get
{
if (this.name == null) {
this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
}
return this.name;
}
get {
if (this.name == null) {
this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
}
return this.name;
}
}
public string Key
@ -356,7 +363,7 @@ namespace DBus
private extern static IntPtr dbus_message_get_interface(IntPtr rawMessage);
[DllImport("dbus-1")]
private extern static bool dbus_message_set_member (IntPtr rawMessage, string name);
private extern static bool dbus_message_set_member(IntPtr rawMessage, string name);
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_get_member(IntPtr rawMessage);

View file

@ -14,20 +14,27 @@ namespace DBus
private string pathName = null;
private Type type = null;
private Introspector introspector = null;
private static AssemblyBuilder proxyAssembly;
private static MethodInfo Service_NameMI = typeof(Service).GetMethod("get_Name",
new Type[0]);
private static MethodInfo Service_ConnectionMI = typeof(Service).GetMethod("get_Connection",
new Type[0]);
private static MethodInfo Service_AddSignalCalledMI = typeof(Service).GetMethod("add_SignalCalled",
new Type[] {typeof(Service.SignalCalledHandler)});
private static MethodInfo Signal_PathNameMI = typeof(Signal).GetMethod("get_PathName",
new Type[0]);
private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
new Type[0]);
private static MethodInfo Message_KeyMI = typeof(Message).GetMethod("get_Key",
new Type[0]);
private static MethodInfo Arguments_InitAppendingMI = typeof(Arguments).GetMethod("InitAppending",
new Type[0]);
private static MethodInfo Arguments_AppendMI = typeof(Arguments).GetMethod("Append",
new Type[] {typeof(DBusType.IDBusType)});
private static MethodInfo Message_SendWithReplyAndBlockMI = typeof(Message).GetMethod("SendWithReplyAndBlock",
new Type[0]);
private static MethodInfo Message_SendMI = typeof(Message).GetMethod("Send",
new Type[0]);
private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
new Type[0]);
private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
@ -42,8 +49,19 @@ namespace DBus
typeof(string),
typeof(string),
typeof(string)});
private static ConstructorInfo Signal_C = typeof(Signal).GetConstructor(new Type[] {typeof(Service),
typeof(string),
typeof(string),
typeof(string)});
private static ConstructorInfo Service_SignalCalledHandlerC = typeof(Service.SignalCalledHandler).GetConstructor(new Type[] {typeof(object),
typeof(System.IntPtr)});
private static MethodInfo String_opEqualityMI = typeof(System.String).GetMethod("op_Equality",
new Type[] {typeof(string),
typeof(string)});
private static MethodInfo MulticastDelegate_opInequalityMI = typeof(System.MulticastDelegate).GetMethod("op_Inequality",
new Type[] {typeof(System.MulticastDelegate),
typeof(System.MulticastDelegate)});
public ProxyBuilder(Service service, Type type, string pathName)
{
@ -53,6 +71,163 @@ namespace DBus
this.introspector = Introspector.GetIntrospector(type);
}
private MethodInfo BuildSignalCalled(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
{
Type[] parTypes = {typeof(Signal)};
MethodBuilder methodBuilder = typeB.DefineMethod("Service_SignalCalled",
MethodAttributes.Private |
MethodAttributes.HideBySig,
typeof(void),
parTypes);
ILGenerator generator = methodBuilder.GetILGenerator();
LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
enumeratorL.SetLocalSymInfo("enumerator");
Label wrongPath = generator.DefineLabel();
//generator.EmitWriteLine("if (signal.PathName == pathName) {");
generator.Emit(OpCodes.Ldarg_1);
generator.EmitCall(OpCodes.Callvirt, Signal_PathNameMI, null);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, pathF);
generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
generator.Emit(OpCodes.Brfalse, wrongPath);
int localOffset = 1;
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
EventInfo eventE = (EventInfo) signalEntry.Value;
// This is really cheeky since we need to grab the event as a private field.
FieldInfo eventF = this.type.GetField(eventE.Name,
BindingFlags.NonPublic|
BindingFlags.Instance);
MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
parTypes = new Type[pars.Length];
for (int parN = 0; parN < pars.Length; parN++) {
parTypes[parN] = pars[parN].ParameterType;
LocalBuilder parmL = generator.DeclareLocal(parTypes[parN]);
parmL.SetLocalSymInfo(pars[parN].Name);
}
Label skip = generator.DefineLabel();
//generator.EmitWriteLine(" if (SelectedIndexChanged != null) {");
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, eventF);
generator.Emit(OpCodes.Ldnull);
generator.EmitCall(OpCodes.Call, MulticastDelegate_opInequalityMI, null);
generator.Emit(OpCodes.Brfalse, skip);
//generator.EmitWriteLine(" if (signal.Key == 'la i')");
generator.Emit(OpCodes.Ldarg_1);
generator.EmitCall(OpCodes.Callvirt, Message_KeyMI, null);
generator.Emit(OpCodes.Ldstr, eventE.Name + " " + InterfaceProxy.GetSignature(eventHandler_InvokeMI));
generator.EmitCall(OpCodes.Call, String_opEqualityMI, null);
generator.Emit(OpCodes.Brfalse, skip);
//generator.EmitWriteLine("IEnumerator enumerator = signal.Arguments.GetEnumerator()");
generator.Emit(OpCodes.Ldarg_1);
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
generator.Emit(OpCodes.Stloc_0);
for (int parN = 0; parN < pars.Length; parN++) {
ParameterInfo par = pars[parN];
if (!par.IsOut) {
EmitSignalIn(generator, par.ParameterType, parN + localOffset, serviceF);
}
}
//generator.EmitWriteLine(" SelectedIndexChanged(selectedIndex)");
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, eventF);
for (int parN = 0; parN < pars.Length; parN++) {
generator.Emit(OpCodes.Ldloc_S, parN + localOffset);
}
generator.EmitCall(OpCodes.Callvirt, eventHandler_InvokeMI, null);
generator.MarkLabel(skip);
//generator.EmitWriteLine(" }");
localOffset += pars.Length;
}
}
generator.MarkLabel(wrongPath);
//generator.EmitWriteLine("}");
//generator.EmitWriteLine("return");
generator.Emit(OpCodes.Ret);
return methodBuilder;
}
private void BuildSignalHandler(EventInfo eventE,
InterfaceProxy interfaceProxy,
ref TypeBuilder typeB,
FieldInfo serviceF,
FieldInfo pathF)
{
MethodInfo eventHandler_InvokeMI = eventE.EventHandlerType.GetMethod("Invoke");
ParameterInfo[] pars = eventHandler_InvokeMI.GetParameters();
Type[] parTypes = new Type[pars.Length];
for (int parN = 0; parN < pars.Length; parN++) {
parTypes[parN] = pars[parN].ParameterType;
}
// Generate the code
MethodBuilder methodBuilder = typeB.DefineMethod("Proxy_" + eventE.Name,
MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.Virtual,
typeof(void),
parTypes);
ILGenerator generator = methodBuilder.GetILGenerator();
for (int parN = 0; parN < pars.Length; parN++) {
methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
}
// Generate the locals
LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
methodCallL.SetLocalSymInfo("signal");
LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
//generator.EmitWriteLine("Signal signal = new Signal(...)");
generator.Emit(OpCodes.Ldsfld, serviceF);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldfld, pathF);
generator.Emit(OpCodes.Ldstr, interfaceProxy.InterfaceName);
generator.Emit(OpCodes.Ldstr, eventE.Name);
generator.Emit(OpCodes.Newobj, Signal_C);
generator.Emit(OpCodes.Stloc_0);
//generator.EmitWriteLine("signal.Arguments.InitAppending()");
generator.Emit(OpCodes.Ldloc_0);
generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
for (int parN = 0; parN < pars.Length; parN++) {
ParameterInfo par = pars[parN];
if (!par.IsOut) {
EmitIn(generator, par.ParameterType, parN, serviceF);
}
}
//generator.EmitWriteLine("signal.Send()");
generator.Emit(OpCodes.Ldloc_0);
generator.EmitCall(OpCodes.Callvirt, Message_SendMI, null);
//generator.EmitWriteLine("return");
generator.Emit(OpCodes.Ret);
}
private void BuildMethod(MethodInfo method,
InterfaceProxy interfaceProxy,
ref TypeBuilder typeB,
@ -145,6 +320,28 @@ namespace DBus
typeB.DefineMethodOverride(methodBuilder, method);
}
private void EmitSignalIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
{
//generator.EmitWriteLine("enumerator.MoveNext()");
generator.Emit(OpCodes.Ldloc_0);
generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
Type outParType = Arguments.MatchType(parType);
//generator.EmitWriteLine("int selectedIndex = (int) ((DBusType.IDBusType) enumerator.Current).Get(typeof(int))");
generator.Emit(OpCodes.Pop);
generator.Emit(OpCodes.Ldloc_0);
generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
generator.Emit(OpCodes.Ldtoken, parType);
generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
// Call the DBusType EmitMarshalOut to make it emit itself
object[] pars = new object[] {generator, parType, true};
outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
generator.Emit(OpCodes.Stloc_S, parN);
}
private void EmitIn(ILGenerator generator, Type parType, int parN, FieldInfo serviceF)
{
Type inParType = Arguments.MatchType(parType);
@ -191,7 +388,7 @@ namespace DBus
}
}
public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF, MethodInfo signalCalledMI)
{
Type[] pars = {typeof(Service), typeof(string)};
ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName |
@ -201,23 +398,102 @@ namespace DBus
ILGenerator generator = constructor.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Call, this.introspector.Constructor);
//generator.EmitWriteLine("service = myService");
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Stsfld, serviceF);
//generator.EmitWriteLine("this.pathName = pathName");
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_2);
generator.Emit(OpCodes.Stfld, pathF);
//generator.EmitWriteLine("myService.SignalCalled += new Service.SignalCalledHandler(Service_SignalCalled)");
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldftn, signalCalledMI);
generator.Emit(OpCodes.Newobj, Service_SignalCalledHandlerC);
generator.EmitCall(OpCodes.Callvirt, Service_AddSignalCalledMI, null);
//generator.EmitWriteLine("return");
generator.Emit(OpCodes.Ret);
}
public void BuildSignalConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo pathF)
{
Type[] pars = {typeof(Service), typeof(string)};
ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName |
MethodAttributes.Public,
CallingConventions.Standard, pars);
ILGenerator generator = constructor.GetILGenerator();
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Call, this.introspector.Constructor);
//generator.EmitWriteLine("service = myService");
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Stsfld, serviceF);
//generator.EmitWriteLine("this.pathName = pathName");
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_2);
generator.Emit(OpCodes.Stfld, pathF);
//generator.EmitWriteLine("return");
generator.Emit(OpCodes.Ret);
}
public object GetProxy()
{
public object GetSignalProxy()
{
Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".SignalProxy");
if (proxyType == null) {
// Build the type
TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".SignalProxy",
TypeAttributes.Public,
this.type);
FieldBuilder serviceF = typeB.DefineField("service",
typeof(Service),
FieldAttributes.Private |
FieldAttributes.Static);
FieldBuilder pathF = typeB.DefineField("pathName",
typeof(string),
FieldAttributes.Private);
BuildSignalConstructor(ref typeB, serviceF, pathF);
// Build the signal handlers
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
EventInfo eventE = (EventInfo) signalEntry.Value;
BuildSignalHandler(eventE, interfaceProxy, ref typeB, serviceF, pathF);
}
}
proxyType = typeB.CreateType();
Type proxyType = ProxyAssembly.GetType(ProxyName);
// Uncomment the following line to produce a DLL of the
// constructed assembly which can then be examined using
// monodis. Note that in order for this to work you should copy
// the client assembly as a dll file so that monodis can pick it
// up.
//Service.ProxyAssembly.Save("proxy.dll");
}
Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
object [] pars = new object[] {Service, pathName};
ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
object instance = constructor.Invoke(pars);
return instance;
}
public object GetProxy()
{
Type proxyType = Service.ProxyAssembly.GetType(ObjectName + ".Proxy");
if (proxyType == null) {
// Build the type
TypeBuilder typeB = ServiceModuleBuilder.DefineType(ProxyName, TypeAttributes.Public, this.type);
TypeBuilder typeB = Service.Module.DefineType(ObjectName + ".Proxy", TypeAttributes.Public, this.type);
FieldBuilder serviceF = typeB.DefineField("service",
typeof(Service),
@ -227,7 +503,8 @@ namespace DBus
typeof(string),
FieldAttributes.Private);
BuildConstructor(ref typeB, serviceF, pathF);
MethodInfo signalCalledMI = BuildSignalCalled(ref typeB, serviceF, pathF);
BuildConstructor(ref typeB, serviceF, pathF, signalCalledMI);
// Build the methods
foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
@ -245,7 +522,7 @@ namespace DBus
// monodis. Note that in order for this to work you should copy
// the client assembly as a dll file so that monodis can pick it
// up.
//ProxyAssembly.Save("proxy.dll");
//Service.ProxyAssembly.Save("proxy.dll");
}
Type [] parTypes = new Type[] {typeof(Service), typeof(string)};
@ -255,43 +532,18 @@ namespace DBus
object instance = constructor.Invoke(pars);
return instance;
}
private ModuleBuilder ServiceModuleBuilder
{
get {
if (Service.module == null) {
Service.module = ProxyAssembly.DefineDynamicModule(Service.Name, "proxy.dll", true);
}
return Service.module;
}
}
private Service Service
private Service Service
{
get {
return this.service;
}
}
private string ProxyName
private string ObjectName
{
get {
return this.introspector.ToString() + ".Proxy";
}
}
private AssemblyBuilder ProxyAssembly
{
get {
if (proxyAssembly == null){
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "DBusProxy";
proxyAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave);
}
return proxyAssembly;
return this.introspector.ToString();
}
}
}

View file

@ -4,6 +4,7 @@ namespace DBus
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
@ -13,12 +14,20 @@ namespace DBus
private string name;
private bool local = false;
private Hashtable registeredHandlers = new Hashtable();
internal ModuleBuilder module = null;
private delegate int DBusHandleMessageFunction(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData);
private DBusHandleMessageFunction filterCalled;
public delegate void SignalCalledHandler(Signal signal);
public event SignalCalledHandler SignalCalled;
private static AssemblyBuilder proxyAssembly;
private ModuleBuilder module = null;
internal Service(string name, Connection connection)
{
this.name = name;
this.connection = connection;
AddFilter();
}
public Service(Connection connection, string name)
@ -67,9 +76,7 @@ namespace DBus
public void RegisterObject(object handledObject,
string pathName)
{
Handler handler = new Handler(handledObject,
pathName,
this);
Handler handler = new Handler(handledObject, pathName, this);
registeredHandlers.Add(handledObject, handler);
}
@ -89,6 +96,38 @@ namespace DBus
return proxy;
}
private void AddFilter()
{
// Setup the filter function
this.filterCalled = new DBusHandleMessageFunction(Service_FilterCalled);
if (!dbus_connection_add_filter(Connection.RawConnection,
this.filterCalled,
IntPtr.Zero,
IntPtr.Zero))
throw new OutOfMemoryException();
// Add a match for signals. FIXME: Can we filter the service?
string rule = "type='signal'";
dbus_bus_add_match(connection.RawConnection, rule, IntPtr.Zero);
}
private int Service_FilterCalled(IntPtr rawConnection,
IntPtr rawMessage,
IntPtr userData)
{
Message message = Message.Wrap(rawMessage, this);
if (message.Type == Message.MessageType.Signal) {
// We're only interested in signals
Signal signal = (Signal) message;
if (SignalCalled != null) {
SignalCalled(signal);
}
}
return (int) Result.NotYetHandled;
}
public string Name
{
get
@ -110,10 +149,51 @@ namespace DBus
}
}
[DllImport ("dbus-1")]
private extern static int dbus_bus_acquire_service (IntPtr rawConnection, string serviceName, uint flags, ref Error error);
internal AssemblyBuilder ProxyAssembly
{
get {
if (proxyAssembly == null){
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "DBusProxy";
proxyAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.RunAndSave);
}
return proxyAssembly;
}
}
internal ModuleBuilder Module
{
get {
if (this.module == null) {
this.module = ProxyAssembly.DefineDynamicModule(Name, "proxy.dll", true);
}
return this.module;
}
}
[DllImport("dbus-1")]
private extern static int dbus_bus_acquire_service(IntPtr rawConnection,
string serviceName,
uint flags, ref Error error);
[DllImport("dbus-1")]
private extern static bool dbus_bus_service_exists(IntPtr rawConnection,
string serviceName,
ref Error error);
[DllImport("dbus-1")]
private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
DBusHandleMessageFunction filter,
IntPtr userData,
IntPtr freeData);
[DllImport("dbus-1")]
private extern static void dbus_bus_add_match(IntPtr rawConnection,
string rule,
IntPtr erro);
[DllImport ("dbus-1")]
private extern static bool dbus_bus_service_exists (IntPtr rawConnection, string serviceName, ref Error error);
}
}

View file

@ -18,6 +18,23 @@ namespace DBus
{
}
public Signal(Service service, string pathName, string interfaceName, string name)
{
this.service = service;
RawMessage = dbus_message_new_signal(pathName, interfaceName, name);
if (RawMessage == IntPtr.Zero) {
throw new OutOfMemoryException();
}
this.pathName = pathName;
this.interfaceName = interfaceName;
this.name = name;
dbus_message_unref(RawMessage);
}
public new string PathName
{
get
@ -56,5 +73,7 @@ namespace DBus
base.Name = value;
}
}
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_new_signal(string pathName, string interfaceName, string name);
}
}

11
mono/SignalAttribute.cs Normal file
View file

@ -0,0 +1,11 @@
using System;
namespace DBus
{
[AttributeUsage(AttributeTargets.Event, AllowMultiple=false, Inherited=true)] public class SignalAttribute : Attribute
{
public SignalAttribute()
{
}
}
}