[Kde-bindings] KDE/kdebindings

Richard Dale rdale at foton.es
Wed Jun 11 09:25:02 UTC 2008


On Tuesday 10 June 2008 13:21:54 Arno Rehn wrote:
> Am Montag 09 Juni 2008 20:49:25 schrieb Richard Dale:
> > On Monday 09 June 2008 18:13:43 Arno Rehn wrote:
> > > Am Montag 09 Juni 2008 15:28:21 schrieb Richard Dale:
> > > > On Monday 09 June 2008 13:28:13 Arno Rehn wrote:
> > > > > > The only thing I don't like is subclassing SmokeInvocation and
> > > > > > giving it a different name in the generated code. That seems
> > > > > > pointless and ugly to me any old static constructor will load the
> > > > > > smoke lib. In the soprano bindings I had a source called
> > > > > > 'Soprano.cs' with this:
> > > > > >
> > > > > > namespace Soprano {
> > > > > >       using Qyoto;
> > > > > >       using System;
> > > > > >       using System.Runtime.InteropServices;
> > > > > >
> > > > > >       public class InitSoprano {
> > > > > >               [DllImport("libsoprano-sharp",
> > > > > > CharSet=CharSet.Ansi)] static extern void Init_soprano();
> > > > > >
> > > > > >               static InitSoprano() {
> > > > > >                       Init_soprano();
> > > > > >               }
> > > > > >       }
> > > > > > }
> > > > > >
> > > > > > And just left SmokeInvocation as it was in the generated code. So
> > > > > > I think we should have a Kimono.cs source with the same thing in
> > > > > > it.
> > > > >
> > > > > My intention was to simplify the code for those who actually use
> > > > > the C# bindings. And a static constructor is called when the class
> > > > > that defines it is used for the first time. Since SmokeInvocation
> > > > > is always used before any other thing, it makes sure that the smoke
> > > > > lib is always loaded. If we put that code into another class that
> > > > > is completely unrelated to the binding, we will always have to call
> > > > > InitFoo() if we want to use it. So subclassing SmokeInvocation for
> > > > > the different bindings seemed to be the best solution to me.
> > > >
> > > > OK, I understand the problem now, but I still think the solution of
> > > > renaming SmokeInvocation is ugly. I found this after a bit of
> > > > googling:
> > > >
> > > > "Note, however, that you *can* put code in your AppDomain to execute
> > > > when *another* DLL loads. (The AppDomain.AssemblyLoad event.) That
> > > > means you can write your code once, and so long as that event handler
> > > > is added before the other assemblies are loaded, you can do all the
> > > > appropriate things."
> > > >
> > > > http://osdir.com/ml/windows.devel.dotnet.cx/2004-01/msg00064.html
> > > >
> > > > So is the Qyoto dll in an AppDomain, or can we put it in one?
> > >
> > > Yes, of couse the Qyoto dll is always in an AppDomain. So we'd have to
> > > define a standard class class name, whoch holds a method to do the
> > > initialization. Whenever an assembly is loaded, we have to look for
> > > that class via reflection and call the initialization method.
> >
> > I've read a bit more about this, and it seems quite straightforward to
> > implement - you just set up a static delegate that receives the dll
> > loaded event and then do what you say. So I would prefer doing it this
> > way - an app domain called 'Qyoto' and an initialize class called
> > InitSmoke in each dll for instance.
>
> Ok, I just tested this and it doesn't quite work out. Consider this:
>
> using System;
> using Qyoto;
>
> class MainClass {
> 	public static void AssemblyLoad(object sender, AssemblyLoadEventArgs args)
> { Console.WriteLine(args.LoadedAssembly.FullName);
> 	}
>
> 	public static void Main(string[] args) {
> 		AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoad;
> // 		System.Reflection.Assembly.Load("qt-dotnet, Version=4.4.0.0,
> Culture=neutral, PublicKeyToken=194a23ba31c08164");
> 	}
> }
>
> This will do nothing, since we add the event handler _after_ the assembly
> is loaded. The same will happen if we define such an event handler in the
> Qyoto runtime. If we load the assembly dynamically, it will work well. So
> going via AppDomain.AssemblyLoad is not really an option, I think.
So when Qyoto.Qyoto.Init_qyoto() is called in the SmokeInvocation static 
constructor all the assemblies are already loaded?

If that is so, I think we just need to add a custom Attribute to the Qyoto 
assemblies (apart from the qt dll):

	[AttributeUsage(AttributeTargets.Assembly)]
	public class AssemblySmokeInitializer : Attribute
	{
		public string initializer;	
	
		public string Initializer {
			get {
				return initializer;
			}
		}
	
		public AssemblySmokeInitializer(string initializer) {
			this.initializer = initializer;
		}
	}

Then in each AssemblyInfo.cs:

// The class to initialize the smoke library used by this assembly
// Type.GetType("Soprano.InitSoprano")
[assembly: AssemblySmokeInitializer("Soprano.InitSoprano")]

Does Type.GetType() load the class? If so, it should called the init method 
for the smoke lib in the InitSoprano class:

namespace Soprano {
	using Qyoto;
	using System;
	using System.Runtime.InteropServices;

	public class InitSoprano {
		[DllImport("libsoprano-sharp", CharSet=CharSet.Ansi)]
		static extern void Init_soprano();
		
		static InitSoprano() {
			Init_soprano();
		}
	}
}

In the SmokeInvocation static constructor we need to iterate though the loaded 
assemblies looking for AssemblySmokeInitializer attributes and load the named 
classes.

-- Richard






More information about the Kde-bindings mailing list