Thread overview
Factory design
May 28, 2006
John C
May 29, 2006
John C
May 29, 2006
Ameer Armaly
May 29, 2006
Carlos Santander
May 28, 2006
So I've got an abstract class with a factory method. Users call the factory method to instantiate an instance. It calls a function which modules that contain the contrete class must implement.

But I'm getting linking errors. OptLink thinks 'createXmlReaderImpl' is undefined, presumably because it's expecting the body to be contained in the same module.

Note that if 'createXmlReaderImpl' is declared with 'extern(C)', then it links without errors.

I've seen a similar technique used before. The main entry point in dmain.d in phobos, for example. Ideas?

module model;

// Modules containing the concrete class implement this.
XmlReader createXmlReaderImpl(Stream input);

abstract class XmlReader {

  static XmlReader create(Stream input) {
    return createXmlReaderImpl(input);
  }

  // Abstract methods...

}

// impl1 implementation wraps some C library.
module impl1;
import model;

XmlReader createXmlReaderImpl(Stream input) {
  return new XmlReaderImpl(input);
}

class XmlReaderImpl : XmlReader {

  // Implements XmlReader's abstract methods

  private this(Stream input) ...

}

// impl2 implementation wraps some other C library.
module impl2;
import model;

XmlReader createXmlReaderImpl(Stream input) {
  return new XmlReaderImpl(input);
}

class XmlReaderImpl : XmlReader {

  // Implements XmlReader's abstract methods

  private this(Stream input) ...

}

// User code that chooses which implementation to use.
module program;
import model, impl1; // Choosing impl1

void main() {
  Stream s = ...;
  XmlReader reader = XmlReader.create(s);
}

Thanks,
John.
May 29, 2006
"John C" <johnch_atms@hotmail.com> wrote in message news:e5ddb1$17kq$1@digitaldaemon.com...

> Note that if 'createXmlReaderImpl' is declared with 'extern(C)', then it links without errors.

Did you try just putting "extern" (or "extern(D)") in front of both the prototype and the definition?


May 29, 2006
Jarrett Billingsley wrote:
> "John C" <johnch_atms@hotmail.com> wrote in message news:e5ddb1$17kq$1@digitaldaemon.com...
> 
> 
>>Note that if 'createXmlReaderImpl' is declared with 'extern(C)', then it links without errors.
> 
> 
> Did you try just putting "extern" (or "extern(D)") in front of both the prototype and the definition? 
> 
> 

I did - I get the same linking errors.

extern(C) works because the name of the function doesn't get mangled.
May 29, 2006
"John C" <johnch_atms@hotmail.com> wrote in message news:e5dgdt$1as6$1@digitaldaemon.com...

> extern(C) works because the name of the function doesn't get mangled.

Ohhhh yeah.  I ran into the same thing on another thread about 15 down from this one..

This is a real problem.  Mangling function names with module names is a good idea on the surface, but it makes it impossible to declare a function in one module and define it in another without some ugly hacks and serious restrictions.

Something needs to be done to solve this, such as not mangling module names into the names of functions which are declared "extern."


May 29, 2006
John C escribió:
> So I've got an abstract class with a factory method. Users call the factory method to instantiate an instance. It calls a function which modules that contain the contrete class must implement.
> 
> But I'm getting linking errors. OptLink thinks 'createXmlReaderImpl' is undefined, presumably because it's expecting the body to be contained in the same module.
> 
> Note that if 'createXmlReaderImpl' is declared with 'extern(C)', then it links without errors.
> 
> I've seen a similar technique used before. The main entry point in dmain.d in phobos, for example. Ideas?
> 
> module model;
> 
> // Modules containing the concrete class implement this.
> XmlReader createXmlReaderImpl(Stream input);
> 

How about putting it in an abstract class, say a singleton?

> abstract class XmlReader {
> 
>   static XmlReader create(Stream input) {
>     return createXmlReaderImpl(input);
>   }
> 
>   // Abstract methods...
> 
> }
> 
> // impl1 implementation wraps some C library.
> module impl1;
> import model;
> 
> XmlReader createXmlReaderImpl(Stream input) {
>   return new XmlReaderImpl(input);
> }
> 
> class XmlReaderImpl : XmlReader {
> 
>   // Implements XmlReader's abstract methods
> 
>   private this(Stream input) ...
> 
> }
> 
> // impl2 implementation wraps some other C library.
> module impl2;
> import model;
> 
> XmlReader createXmlReaderImpl(Stream input) {
>   return new XmlReaderImpl(input);
> }
> 
> class XmlReaderImpl : XmlReader {
> 
>   // Implements XmlReader's abstract methods
> 
>   private this(Stream input) ...
> 
> }
> 
> // User code that chooses which implementation to use.
> module program;
> import model, impl1; // Choosing impl1
> 
> void main() {
>   Stream s = ...;
>   XmlReader reader = XmlReader.create(s);
> }
> 
> Thanks,
> John.


-- 
Carlos Santander Bernal
May 29, 2006
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message news:e5dju8$1dol$1@digitaldaemon.com...
> "John C" <johnch_atms@hotmail.com> wrote in message news:e5dgdt$1as6$1@digitaldaemon.com...
>
>> extern(C) works because the name of the function doesn't get mangled.
>
> Ohhhh yeah.  I ran into the same thing on another thread about 15 down from this one..
>
> This is a real problem.  Mangling function names with module names is a good idea on the surface, but it makes it impossible to declare a function in one module and define it in another without some ugly hacks and serious restrictions.
>
> Something needs to be done to solve this, such as not mangling module names into the names of functions which are declared "extern."
I agree.  Perhaps with some sort of marker to designate them as module-independent if you will; you would be saying with extern that this function is meant to be declared anywhere.
>
>