Aliasing specialized template stuct in his module leads troubles

Mike Parker aldacron at gmail.com
Tue Sep 4 18:50:28 PDT 2012


On 9/5/2012 7:46 AM, Ivan Agafonov wrote:
> I have my library module:
> ========================================================
> module mylib.vector;
>
> // alias Vector!(float, 4) Vector4f;
>
> struct Vector(T, uint size)
> {
>      T[size] array = 0;
>      ...
> }
> ========================================================
>
> And I have client module:
> ========================================================
> import mylib.vector;
>
> alias Vector!(float, 4) Vector4f;
>
> void main()
> {
>      auto x = Vector4f([1.0f, 2.0f, 3.0f, 4.0f]);
> }
> ========================================================
>
> If alias would be in vector module (commented there) I will have to compile
> both modules (otherwise I'll get link errors for some vector functions),
> but I want to simply import vector module and immediately use predefined
> aliases for vector template struct. How can I do this?

If I understand your issue correctly, it isn't a "problem". It's the way 
D is designed to work. Simply importing a module does not mean that you 
do not also need to compile and link it in your program.

What importing does is make the symbols (declarations, definitions and 
so on) in the module available at compile time so that the compiler can 
know what is and isn't visible to the module it is currently compiling. 
But if there are any symbols in the imported module that need to be 
present at link time (such as variable declarations), then the imported 
module needs to be compiled and linked as well. In other words, it 
doesn't work like Java, where importing a class file causes the related 
class to be loaded a runtime.

Take the following example:

=============================
// foo.d
module foo;

struct Bar
{
     int x;
}

// baz.d
module baz;

import foo;

void main()
{
     Bar bar;
     bar.x = 1;
}
=============================

You can compile this example like so:

dmd baz.d

And you wind up with a working program. The struct definition in foo.d 
is just a definition. The compiler uses it to know what is and isn't 
callable on Bar, how much memory an instance of it needs, and so on. So 
you can declare and instantiate instances of it in other modules without 
compiling and linking the foo module. Now let's change it up a bit:

============================
// foo.d
module foo;

struct Bar
{
     int x;
}

// Declare an instance of Bar here in the foo module
Bar foobar;

// baz.d
module baz;

import foo;

void main()
{
     Bar bar;
     bar.x = 1;

     foobar.x = 2;
}
============================

Now compile like so:

dmd baz.d

And this happens:

============================
OPTLINK (R) for Win32  Release 8.00.12
Copyright (C) Digital Mars 1989-2010  All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
baz.obj(baz)
  Error 42: Symbol Undefined _D3foo6foobarS3foo3Bar
--- errorlevel 1
============================

The reason is because when the compile processes baz.d, it sees that it 
uses the variable foobar. That variable is not found in the baz module, 
but it is publicly visible in the foo module which baz imports. So the 
compiler says, ok, this is no problem. It goes about its job and creates 
baz.obj and passes it off to the linker. The linker looks through 
baz.obj, finds a reference to foobar, which, given the name mangling 
(_D3foo6foobarS3foo3Bar), should exist in an object file called foo (the 
linker knows nothing about D modules). So the linker wants to take 
foo.obj and link it together with bar.obj to create the final 
executable. Only, there is no foo.obj because you didn't compile it.

dmd baz.d foo.d

Now both object files can be created and linked together to make the 
final executable.

A template alias actually instantiates a template. A template 
instantiation must be available to the linker. So if you instantiate in 
the vector module, you *must* compile and link it. Generally, you should 
either pass all the modules you import along to the compiler, or link 
with a library in which those modules have been compiled. This way, you 
don't have to worry about what is declared or instantiated where.





More information about the Digitalmars-d-learn mailing list