Thread overview
RTTI : how to create object from name
Oct 26, 2004
LiuXuHong
Oct 26, 2004
Stewart Gordon
Oct 26, 2004
h3r3tic
Oct 27, 2004
Stewart Gordon
Oct 27, 2004
h3r3tic
Oct 27, 2004
Stewart Gordon
Oct 28, 2004
h3r3tic
Oct 26, 2004
Ben Hinkle
October 26, 2004
// It's easy to create object using the RTTI mechanism in D. e.g.

class AAA {} // actually it derived from Object

// we can create AAA like this, classinfo is a static member of AAA
AAA a = cast(AAA)cast(void*)AAA.classinfo.init;

// but how can we create AAA just use the class name "AAA", like this

AAA a1 = someImpementation("AAA");



I am from Shanghai, China.
Nice to meet you here :)
October 26, 2004
LiuXuHong wrote:

> // It's easy to create object using the RTTI mechanism in D. e.g.
> 
> class AAA {} // actually it derived from Object
> 
> // we can create AAA like this, classinfo is a static member of AAA
> AAA a = cast(AAA)cast(void*)AAA.classinfo.init;

Surely that isn't creating an AAA, but creating a reference to a static AAA?

> // but how can we create AAA just use the class name "AAA", like this
> 
> AAA a1 = someImpementation("AAA");

AIUI you can't do it directly.  But you could create an associative array listing all the classes in your app that are going to be subjectable to this behaviour....

Is this for anything particular?

Stewart.
October 26, 2004
LiuXuHong wrote:
> // It's easy to create object using the RTTI mechanism in D. e.g.
> 
> class AAA {} // actually it derived from Object
> 
> // we can create AAA like this, classinfo is a static member of AAA
> AAA a = cast(AAA)cast(void*)AAA.classinfo.init;
> 
> // but how can we create AAA just use the class name "AAA", like this
> 
> AAA a1 = someImpementation("AAA");


here's my solution to the problem...
I have the objfactory.d file:
// -----------------------------------------------------
// do not instantiate this struct. it's meant to be >>The ONE<<
struct factory
{
	static Object function()[char[]] 	n2o;
	static char[][ClassInfo]			o2n;

	class type(T)
	{
		static Object createObj()
		{
			return new T;
		}
	
		this()
		{
			factory.n2o[T.classinfo.name]	= &createObj;
			factory.o2n[T.classinfo]		= T.classinfo.name;
		}
		
		this(char[] name)
		{
			factory.n2o[name]			= &createObj;
			factory.o2n[T.classinfo]	= name;
		}
	}
	
	char[] nameOf(Object obj)
	{
		return o2n[obj.classinfo];
	}

	static Object make(char[] name)
	{
		if ( name in n2o ) return n2o[name]();
		else throw new Error("unknown class requested from the factory: " ~ name);
	}
}
// --------------------------------------------------------


Now you can register some types into the factory with:

	new factory.type!(Foo);
	new factory.type!(Bar)("main.bar");
	new factory.type!(Baz);

e.g. in the module's static ctor.


Objects are created with:
	Object result = factory.make(name);


Hope this helps

Tom
October 26, 2004
"LiuXuHong" <LiuXuHong_member@pathlink.com> wrote in message news:clm0co$2qcm$1@digitaldaemon.com...
> // It's easy to create object using the RTTI mechanism in D. e.g.
>
> class AAA {} // actually it derived from Object
>
> // we can create AAA like this, classinfo is a static member of AAA
> AAA a = cast(AAA)cast(void*)AAA.classinfo.init;
>
> // but how can we create AAA just use the class name "AAA", like this
>
> AAA a1 = someImpementation("AAA");
>
>
>
> I am from Shanghai, China.
> Nice to meet you here :)

Here's something that doesn't work but maybe some can fix it so that it does. The GetProcAddress always returns null for me - maybe the symbol doesn't exist or isn't exported or maybe I'm poking at the wrong symbol. I don't know.

module reflect;

import std.loader;
import std.string;
import std.c.windows.windows;

extern (C) Object _d_newclass(ClassInfo ci); // no ctor called - just
inited!

Object newInstance(char[] name) {
  char[] mangled;
  HMODULE exe = GetModuleHandleA(null); // get executable
  while (name.length > 0) {
    int dot = find(name,'.');
    if (dot != -1) {
      mangled ~= toString(dot) ~ name[0 .. dot];
      name = name[dot+1 .. name.length];
    } else {
      mangled ~= toString(name.length) ~ name;
      name = "";
    }
  }
  mangled = "__Class_" ~ mangled;
  FARPROC ptr = GetProcAddress(exe,mangled);
  printf("ptr = %p\n",ptr);
  return _d_newclass(cast(ClassInfo)ptr);
}

class AAA {
  int x;
}

int main() {
  Object a = newInstance("reflect.AAA");
  return 0;
}


October 27, 2004
h3r3tic wrote:
<snip>
> I have the objfactory.d file:
> // -----------------------------------------------------
> // do not instantiate this struct. it's meant to be >>The ONE<<
<snip>

Then why bother making it a struct?  Why not just a module?

Stewart.
October 27, 2004
Stewart Gordon wrote:
> h3r3tic wrote:
> <snip>
> 
>> I have the objfactory.d file:
>> // -----------------------------------------------------
>> // do not instantiate this struct. it's meant to be >>The ONE<<
> 
> <snip>
> 
> Then why bother making it a struct?  Why not just a module?
> 
> Stewart.

So that one's forced to access this struct's members using 'factory.'
e.g. this is ok: new factory.type!(Foo);
but this gives an error: new type!(Foo);

Or can that be done with a module as well ? :>
October 27, 2004
h3r3tic wrote:
<snip>
> So that one's forced to access this struct's members using 'factory.'
> e.g. this is ok: new factory.type!(Foo);
> but this gives an error: new type!(Foo);
> 
> Or can that be done with a module as well ? :>

If you think

    new type!(Foo);

isn't long enough to prevent accidents, give the class a longer name. Otherwise, what's the point?

Stewart.
October 28, 2004
Stewart Gordon wrote:
> h3r3tic wrote:
> <snip>
> 
>> So that one's forced to access this struct's members using 'factory.'
>> e.g. this is ok: new factory.type!(Foo);
>> but this gives an error: new type!(Foo);
>>
>> Or can that be done with a module as well ? :>
> 
> 
> If you think
> 
>     new type!(Foo);
> 
> isn't long enough to prevent accidents, give the class a longer name. Otherwise, what's the point?
> 
> Stewart.

Whatever... that's just a philosophical choice...