www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Linker error

reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
So, I have the following two files:

skeleton.d:
```d
/*skeleton.d by Ruby The Roobster*/
/*Version 1.0 Release*/
/*Module for representing skeletons in the D Programming Language 
2.0*/
/*This program is free software: you can redistribute it and/or 
modify
it under the terms of the GNU General Public License as published 
by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
<http://www.gnu.org/licenses/>.*/
/** Copyright: 2021, Ruby The Roobster*/
/**Author: Ruby The Roobster, michaeleverestc79 gmail.com*/
/**Date: October 1, 2021*/
/** License:  GPL-3.0*/
module dutils.skeleton;
/**Struct for representing a point.*/
public struct Point	{ //Point structure...
	///Point.x is the 'x' coordinate of the point.
	real x;
	///Point.y is the 'y' coordinate of the point.
	real y;
	///Point.z is the 'z' coordinate of the point.
	real z;
	void opAssign(Point rhs)	{
		this.x = rhs.x;
		this.y = rhs.y;
		this.z = rhs.z;
	}
	void opOpAssign(string op)(Point rhs)	{
		mixin("this.x " ~ op ~ "= rhs.x;");
		mixin("this.y " ~ op ~ "= rhs.y;");
		mixin("this.z " ~ op ~ "= rhs.z;");
	}
}
/**Struct for representing a face of a skeleton that is made out 
of lines.*/
public struct Face	{ //Face(of a 3D shape) structure...
	///Face.lines is an array of all the lines that connect to form 
the face.
	Line[] lines;
	///Face.center is the center point of the face.
	Point center;
	void opAssign(Face rhs)	{
		this.lines.length = rhs.lines.length;
		foreach(i;0 .. this.lines.length)	{
			this.lines[i] = rhs.lines[i];
		}
	}
}
/**Struct for representing a 3D skeleton.*/
public struct Skeleton	{ //Skeleton of a 3D structure...
	///Skeleton.faces is an array of the faces that make up the 
Skeleton.
	Face[] faces;
	///Skeleton.center is the center point of the skeleton.
	Point center;
	void opAssign(Skeleton rhs)	{
		this.faces.length = rhs.faces.length;
		foreach(i;0 .. this.faces.length)	{
			this.faces[i] = rhs.faces[i];
		}
		this.center = rhs.center;
	}
}

/**Struct for representing a line composed of at least a starting 
point and an end point.
   *Notes:
   *This struct doesn't check to make sure that the line made is 
an actual line and assumes the user knows what they are doing.
*/
public struct Line	{ //Line struct...
	///Line.mid_points is an array containing all of the points that 
are neither start nor end points.
	Point[] mid_points;
	///Line.start is the start point of the line.
	Point start;
	///Line.end is the end point of the line.
	Point stop;
	void opAssign(Line rhs)	{
		this.start = rhs.start;
		this.stop = rhs.stop;
		this.mid_points.length = rhs.mid_points.length;
		foreach(i;0 .. this.mid_points.length)	{
			this.mid_points[i] = rhs.mid_points[i];
		}
	}
}
```

physics.d:
```d
/*physics.d by Ruby The Roobster*/
/*Version 0.35 testing*/
/*Module for basic physics in the D Programming Language 2.0*/
/*This program is free software: you can redistribute it and/or 
modify
it under the terms of the GNU General Public License as published 
by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
<http://www.gnu.org/licenses/>.*/
/** Copyright: 2021, Ruby The Roobster*/
/**Author: Ruby The Roobster, michaeleverestc79 gmail.com*/
/**Date: October 11, 2021*/
/** License: GPL-3.0*/
module dutils.physics;
public import dutils.skeleton;

package mixin template move__()	{
	pragma(inline) package void mv(Point moveby, ref Skeleton 
tomove)	{
		foreach(i;tomove.faces)	{
			foreach(k;i.lines)	{
				foreach(j;k.mid_points)	{
					j += moveby;
				}
				k.start += moveby;
				k.stop += moveby;
			}
			i.center += moveby;
		}
		tomove.center += moveby;
	}
}
/**
   * move moves all the points in a skeleton to a specified point 
with a specified time gap between moving the points.
   * Params:
   * moveto=	A point specifying the total amount to move along 
each axis.
   * tbf=	The time in miliseconds between 'frames'(a frame is one 
section of moving points before waiting a bit).  This gives an 
illusion of continuous motion.
   * tomove=	The skeleton being moved.
   * speed=	The speed at which to move the points.
   * Returns:
   * none
*/
public void move(Point moveto, uint tbf, ref Skeleton tomove, 
real speed)	{
	import core.thread;
	mixin move__;
	Point moveby;
	moveby.x = moveto.x / speed;
	moveby.y = moveto.y / speed;
	moveby.z = moveto.z / speed;
	while(!((tomove.center.x > moveto.x && moveto.x > 0) ^ 
(tomove.center.x < moveto.x && moveto.x < 0)))	{
		mv(moveby, tomove);
		debug import std.stdio : writeln;
		debug writeln(tomove.center);
		Thread.sleep(dur!"msecs"(tbf));
	}
	foreach(i;tomove.faces)	{
		foreach(j;i.lines)	{
			foreach(k;j.mid_points)	{
				k += moveto;
			}
			j.start += moveto;
			j.stop += moveto;
		}
		i.center += moveto;
	}
	tomove.center += moveto;
	debug import std.stdio : writeln;
	debug writeln(tomove.center);
}

public void accMove()	{
}

public void decMove()	{
}
```

Now, here is a test file I am using to test the 'move()' function 
in physics.d:

```d
import dutils.physics;
void main()	{
	Skeleton skele = Skeleton([Face([Line(new 
Point[0],Point(0,0,0),Point(0,0,0))],Point(0,0,0))],Point(0,0,0));
	move(Point(1,1,1),10, skele, 0.01);
}
```

And here is the error I am getting from the linker(optlink):

Error 42: Symbol Undefined 
__D6dutils7physics4moveFSQw8skeleton5PointkKSQBqQv8SkeletoneZ8__mixin52mvMFNaNbNiNfQChKQBrZv

The command line is as follows(tst.d is the name of my test file, 
and the other files are in the same directory):

dmd tst.d physics.d skeleton.d -debug

Compiler is dmd 2.098.0.
Thanks in advance.
Oct 11 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Monday, 11 October 2021 at 23:43:17 UTC, Ruby The Roobster 
wrote:
 package mixin template move__()	{
 	pragma(inline) package void mv(Point moveby, ref Skeleton 
 tomove)	{
 		foreach(i;tomove.faces)	{
 			foreach(k;i.lines)	{
 				foreach(j;k.mid_points)	{
 					j += moveby;
 				}
 				k.start += moveby;
 				k.stop += moveby;
 			}
 			i.center += moveby;
 		}
 		tomove.center += moveby;
 	}
 }
It compiles if this `pragma(inline)` is removed.
Oct 11 2021
parent bauss <jj_1337 live.dk> writes:
On Tuesday, 12 October 2021 at 00:01:25 UTC, jfondren wrote:
 On Monday, 11 October 2021 at 23:43:17 UTC, Ruby The Roobster 
 wrote:
 package mixin template move__()	{
 	pragma(inline) package void mv(Point moveby, ref Skeleton 
 tomove)	{
 		foreach(i;tomove.faces)	{
 			foreach(k;i.lines)	{
 				foreach(j;k.mid_points)	{
 					j += moveby;
 				}
 				k.start += moveby;
 				k.stop += moveby;
 			}
 			i.center += moveby;
 		}
 		tomove.center += moveby;
 	}
 }
It compiles if this `pragma(inline)` is removed.
Not to mention there is no point in marking mv with either pragma(inline) or package. It's mixed into the function move(), which means it cannot be accessed outside of the function anyway, so that makes package unnecessary. Inline will probably do nothing as the inline really just tells the compiler it should inline if it can or wants to, it's not a guarantee and it probably can't inline the function in this case.
Oct 12 2021