www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - newbie confusion with arrays and structs

reply Robert Bernecky <bernecky snakeisland.com> writes:
Hi. I am trying to write my first D program, and am quite stuck in several
areas. This is on Ubuntu 10.10 with the dmd DMD64 D Compiler v2.055.

I want to create a generic struct for multi-dimensional arrays,
in which the value parts can be shared. E.g., an array comprises
a vector of its raveled elements, and an integer shape vector
comprising the length of each axis. Thus, a 2x4 matrix of
the integers [0,1,2,3,4,5,6,7] would have a shape vector of [2,4],
and a value of the integers above, contained in a Parray struct, as
shown in attachment 1. The calling environment is in prd.d.

I want to be able to share shape vectors and values. For example,
the above matrix might also have its value referenced by its raveled
cousin, whose Parray shape would be [8].

I get the impression that calling by ref on Parray is what I want, as long
as anything that wants to modify a Parray shape or value element explicitly
copies the relevant part.

However, none of this stuff works. Here's what I get:

dmd prd.d -unittest

prd.o:(.data+0x250): undefined reference to `_D5Array12__ModuleInfoZ'
prd.o:(.data._D23TypeInfo_S5Array6Parray6__initZ+0x28): undefined reference to
`_D5Array6Parray6__initZ'
prd.o: In function `_D3prd4iotaFiZPS5Array6Parray':
prd.d:(.text._D3prd4iotaFiZPS5Array6Parray+0x101): undefined reference to
`_D5Array6Parray6__ctorMFNcAiAiZS5Array6Parray'
collect2: ld returned 1 exit status
--- errorlevel 1

This is not exactly illuminating, and I have no idea what sort of dumb
mistake(s) I'm making in the code.

Suggestions and educational pointers are very welcome!

Thanks,
Robert
Jan 26 2012
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jan 26, 2012 at 08:34:12PM +0000, Robert Bernecky wrote:
 Hi. I am trying to write my first D program, and am quite stuck in several
 areas. This is on Ubuntu 10.10 with the dmd DMD64 D Compiler v2.055.

 However, none of this stuff works. Here's what I get:
 
 dmd prd.d -unittest
 
 prd.o:(.data+0x250): undefined reference to `_D5Array12__ModuleInfoZ'
 prd.o:(.data._D23TypeInfo_S5Array6Parray6__initZ+0x28): undefined reference to
 `_D5Array6Parray6__initZ'
 prd.o: In function `_D3prd4iotaFiZPS5Array6Parray':
 prd.d:(.text._D3prd4iotaFiZPS5Array6Parray+0x101): undefined reference to
 `_D5Array6Parray6__ctorMFNcAiAiZS5Array6Parray'
 collect2: ld returned 1 exit status
 --- errorlevel 1
 
 This is not exactly illuminating, and I have no idea what sort of dumb
 mistake(s) I'm making in the code.

Is Parray defined in another module? If so, you need to include it on your commandline: dmd prd.d parray.d -unittest T -- There are four kinds of lies: lies, damn lies, and statistics.
Jan 26 2012
prev sibling next sibling parent reply "Jesse Phillips" <jessekphillips+D gmail.com> writes:
The important mangled message here is:

prd.o:(.data+0x250): undefined reference to 
`_D5Array12__ModuleInfoZ'

This is a linker error, your code compiled fine. The English 
translation:

"There is an undefined reference to module Array"

You are compiling without including all files you need

dmd prd.d Array.d -unittest

That should at least get you to the next error. Also name your 
modules with lowercase, this isn't required but is a suggestion.
Jan 26 2012
parent Robert Bernecky <bernecky snakeisland.com> writes:
Awesome! I feel much better now; thank you both for your instant help!

dmd prd.d Array.d -unittest

rbe rattler:~/plural$ prd
[0]
[0, 1, 2, 3, 4]
Created int
 iota shape is %d
[0]
 iota value is %d
[0, 1, 2, 3, 4]
got to unittest for Array.d
[0]
[0, 1, 2, 3, 4]
Created int
[0]
[0, 1, 2, 3, 4]
rbe rattler:~/plural$ dmd prd.d Array.d
rbe rattler:~/plural$ prd
[0]
[0, 1, 2, 3, 4]
Created int
[0]
[0, 1, 2, 3, 4]

I found it odd that the import Array.d in prd.d
was not adequate to bring in Array.d, though...
In the interest of science, I tried this:

ls
Array.d  crud2.d  crud3.d  crud.o   plusSA.d      prddmd    prd.original.d
UnitTestArray.d
Array.o  crud2.o  crud3.o  hello.d  prd.backup.d  prddmd.d  prd.works.d
crud2    crud3    crud.d   plusSA   prd.d         prd.o     UnitTestArray
rbe rattler:~/plural$ dmd prd.d -I.
prd.o:(.data+0x218): undefined reference to `_D5Array12__ModuleInfoZ'
prd.o:(.data._D23TypeInfo_S5Array6Parray6__initZ+0x28): undefined reference to
`_D5Array6Parray6__initZ'
prd.o: In function `_D3prd4iotaFiZPS5Array6Parray':
prd.d:(.text._D3prd4iotaFiZPS5Array6Parray+0x101): undefined reference to
`_D5Array6Parray6__ctorMFNcAiAiZS5Array6Parray'
collect2: ld returned 1 exit status
--- errorlevel 1

At any rate, I am back on my training wheels again, and thank both Teoh and
Phillips!

ps: Hereafter, I promise to name my modules in lower case.
    Mea culpa and all that!
Jan 26 2012
prev sibling next sibling parent Justin Whear <justin economicmodeling.com> writes:
On Thu, 26 Jan 2012 21:53:39 +0000, Robert Bernecky wrote:

 Awesome! I feel much better now; thank you both for your instant help!
 
 dmd prd.d Array.d -unittest
 
 rbe rattler:~/plural$ prd
 [0]
 [0, 1, 2, 3, 4]
 Created int
  iota shape is %d
 [0]
  iota value is %d
 [0, 1, 2, 3, 4]
 got to unittest for Array.d
 [0]
 [0, 1, 2, 3, 4]
 Created int
 [0]
 [0, 1, 2, 3, 4]
 rbe rattler:~/plural$ dmd prd.d Array.d rbe rattler:~/plural$ prd
 [0]
 [0, 1, 2, 3, 4]
 Created int
 [0]
 [0, 1, 2, 3, 4]
 
 I found it odd that the import Array.d in prd.d was not adequate to
 bring in Array.d, though... In the interest of science, I tried this:
 
 ls
 Array.d  crud2.d  crud3.d  crud.o   plusSA.d      prddmd   
 prd.original.d UnitTestArray.d
 Array.o  crud2.o  crud3.o  hello.d  prd.backup.d  prddmd.d  prd.works.d
 crud2    crud3    crud.d   plusSA   prd.d         prd.o    
 UnitTestArray rbe rattler:~/plural$ dmd prd.d -I.
 prd.o:(.data+0x218): undefined reference to `_D5Array12__ModuleInfoZ'
 prd.o:(.data._D23TypeInfo_S5Array6Parray6__initZ+0x28): undefined
 reference to `_D5Array6Parray6__initZ'
 prd.o: In function `_D3prd4iotaFiZPS5Array6Parray':
 prd.d:(.text._D3prd4iotaFiZPS5Array6Parray+0x101): undefined reference
 to `_D5Array6Parray6__ctorMFNcAiAiZS5Array6Parray' collect2: ld returned
 1 exit status
 --- errorlevel 1
 
 At any rate, I am back on my training wheels again, and thank both Teoh
 and Phillips!
 
 ps: Hereafter, I promise to name my modules in lower case.
     Mea culpa and all that!

In the interest of saving you some trouble later on, I thought I'd explain why the import statement doesn't automatically "bring in" the referenced file. When you compile, you need to give DMD the names of all the files which need to be turned into object code (thus you must specify "Array.d" on the command line). This is in contrast to linking your code against already-compiled stuff (the std library is a good example), which you do not need to provide for compilation. DMD is quietly passing the std library object file to the linker which is why you don't get linker errors. If you want your Array code to be a separate library/project, you can compile it like so: dmd Array.d -lib Then when you compile your other project: dmd prd.d -I/location/of/Array.d -L/location/of/Array.so Note that some automated build tools can parse your import statements and figure out what files need to be included in the dmd command. Justin
Jan 26 2012
prev sibling parent "Jesse Phillips" <jessekphillips+D gmail.com> writes:
On Thursday, 26 January 2012 at 22:10:23 UTC, Justin Whear wrote:
 If you want your Array code to be a separate library/project, 
 you can compile it like so:
 dmd Array.d -lib

 Then when you compile your other project:
 dmd prd.d -I/location/of/Array.d -L/location/of/Array.so

 Justin

It is actually a little more than that. dmd array.d -lib -oflibarray.a dmd does no currently generate shared libraries, so .a (archive) is used. dmd prd.d -I. -L-L. -L-larray -I (Include directory, used by compiler for locating "header" files. These are used by the compiler to verify the calls you are making into the library, and to generate code from templates if those are being used) -L-L (Pass to the linker the flag -L. The ld linker flag -L is for the library search path) -L-l (Pass the linker the flag -l. The ld linker flag -l request that a library be linked) Libraries are named starting with lib by Unix convention. When passing the library name this is left off (-lm load libm.so or libm.a). I believe you can leave it on though (-llibm) but am not sure. The reason DMD does not compile imported libraries is because of two reasons. When the magic stops working you still have to deal with and understand these steps. The compiler is busy with its job of converting code, it should be helping other tools to make its job simple ("Compiler as a Service"). You will find rdmd is distributed with dmd: rdmd prd.d
Jan 26 2012