www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - I'm getting an unhelpful linker error, what've I got wrong?

reply pineapple <meapineapple gmail.com> writes:
When I attempt to compile my code I get the same linker error 
with both dmd and ldc2. I know where the problematic code is, as 
I don't get the error when I comment out lines 102 through 107, 
but I don't understand why it's bad. I must have some 
misconceptions about how templates work? Is there any way to get 
more descriptive errors out of the compiler if this sort of thing 
happens again in the future?

Here's the code:

     http://pastebin.com/kGUPVa59

Here's the problematic lines:

     final streamint writestring(in char[] str){
         return this.writebuffer!char(str.ptr, str.length);
     }
     final streamint writestring(in string str){
         return this.writebuffer!char(str.ptr, str.length);
     }

And the linker error:

     Undefined symbols for architecture x86_64:
       
"_D6stream6Stream19__T11writebufferTaZ11writebufferMFxPaxlZl", 
referenced from:
           _D6stream6Stream11writestringMFxAaZl in stream.o
           _D6stream6Stream11writestringMFxAyaZl in stream.o
     ld: symbol(s) not found for architecture x86_64
     clang: error: linker command failed with exit code 1 (use -v 
to see invocation)
     --- errorlevel 1
Oct 28 2015
parent reply tcak <1ltkrs+3wyh1ow7kzn1k sharklasers.com> writes:
On Wednesday, 28 October 2015 at 11:11:01 UTC, pineapple wrote:
 When I attempt to compile my code I get the same linker error 
 with both dmd and ldc2. I know where the problematic code is, 
 as I don't get the error when I comment out lines 102 through 
 107, but I don't understand why it's bad. I must have some 
 misconceptions about how templates work? Is there any way to 
 get more descriptive errors out of the compiler if this sort of 
 thing happens again in the future?

 Here's the code:

     http://pastebin.com/kGUPVa59

 Here's the problematic lines:

     final streamint writestring(in char[] str){
         return this.writebuffer!char(str.ptr, str.length);
     }
     final streamint writestring(in string str){
         return this.writebuffer!char(str.ptr, str.length);
     }

 And the linker error:

     Undefined symbols for architecture x86_64:
       
 "_D6stream6Stream19__T11writebufferTaZ11writebufferMFxPaxlZl", 
 referenced from:
           _D6stream6Stream11writestringMFxAaZl in stream.o
           _D6stream6Stream11writestringMFxAyaZl in stream.o
     ld: symbol(s) not found for architecture x86_64
     clang: error: linker command failed with exit code 1 (use 
 -v to see invocation)
     --- errorlevel 1
The "writebuffer" is defined to take an array as parameter. Yet, you are passing a pointer and a length to it. Instead, pass the parameter "str" to it directly. Also, you do not have to put "!char" to there. Compiler will solve it out by itself.
Oct 28 2015
parent reply pineapple <meapineapple gmail.com> writes:
On Wednesday, 28 October 2015 at 11:40:14 UTC, tcak wrote:
 The "writebuffer" is defined to take an array as parameter. 
 Yet, you are passing a pointer and a length to it. Instead, 
 pass the parameter "str" to it directly. Also, you do not have 
 to put "!char" to there. Compiler will solve it out by itself.
There's also a writebuffer method in the interface with this signature, though: streamint writebuffer(T)(in T* buffer, in streamint count); And regardless, changing the problematic code to this doesn't address the linker error: final streamint writestring(in char[] str){ return this.writebuffer(str); } final streamint writestring(in string str){ return this.writebuffer(str); }
Oct 28 2015
next sibling parent reply Kagamin <spam here.lot> writes:
On Wednesday, 28 October 2015 at 11:48:27 UTC, pineapple wrote:
 There's also a writebuffer method in the interface with this 
 signature, though:

     streamint writebuffer(T)(in T* buffer, in streamint count);
Interface can't have templated virtual instance methods.
Oct 28 2015
parent reply pineapple <meapineapple gmail.com> writes:
On Wednesday, 28 October 2015 at 12:06:14 UTC, Kagamin wrote:
 On Wednesday, 28 October 2015 at 11:48:27 UTC, pineapple wrote:
 There's also a writebuffer method in the interface with this 
 signature, though:

     streamint writebuffer(T)(in T* buffer, in streamint count);
Interface can't have templated virtual instance methods.
What might be my options for restructuring the code to avoid this, ideally without sacrificing functionality? I imagine I must be able to use a void pointer instead? But that's just ugly. Maybe I could do something like this? streamint writebuffer(in void* buffer, in streamint count); final streamint writebuffer(T){in T* buffer, in streamint count){ return this.writebuffer(cast(void*) buffer, sizeof(*buffer) * count); }
Oct 28 2015
parent Kagamin <spam here.lot> writes:
     streamint writebuffer(in ubyte[] buffer);
     final streamint writebuffer(T)(in T* buffer, in streamint 
count){
         return this.writebuffer(cast(ubyte[])buffer[0..count]);
     }
Oct 28 2015
prev sibling parent tcak <1ltkrs+3wyh1ow7kzn1k sharklasers.com> writes:
On Wednesday, 28 October 2015 at 11:48:27 UTC, pineapple wrote:
 On Wednesday, 28 October 2015 at 11:40:14 UTC, tcak wrote:
 The "writebuffer" is defined to take an array as parameter. 
 Yet, you are passing a pointer and a length to it. Instead, 
 pass the parameter "str" to it directly. Also, you do not have 
 to put "!char" to there. Compiler will solve it out by itself.
There's also a writebuffer method in the interface with this signature, though: streamint writebuffer(T)(in T* buffer, in streamint count); And regardless, changing the problematic code to this doesn't address the linker error: final streamint writestring(in char[] str){ return this.writebuffer(str); } final streamint writestring(in string str){ return this.writebuffer(str); }
This still doesn't solve everything, but the first thing to do is to define a method for those in the interface as well. streamint writebuffer(T)(in T* buffer, in streamint count) streamint writebuffer(T)(in T* buffer, in streamint count, bool dynamic);
Oct 28 2015