mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 08:48:07 +02:00
Added signal support.
This commit is contained in:
parent
7dd5704023
commit
45277e93d8
10 changed files with 552 additions and 114 deletions
|
|
@ -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
45
mono/ErrorMessage.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
11
mono/SignalAttribute.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
|
||||
namespace DBus
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Event, AllowMultiple=false, Inherited=true)] public class SignalAttribute : Attribute
|
||||
{
|
||||
public SignalAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue