Re: Help passing D strings to C libs
On Monday, March 14, 2011 10:54:57 Trass3r wrote: > > I'm having trouble passing D strings (char[]) to SDL, in particular > > SDL_LoadBMP(), I keep receiving a segfault. > > > > Heres the code: > > > > void setImg(string path) { > > > > // concat null terminating char to string and cast to c type string > > > > when > > > > // passing to SDL_LoadBMP() > > path ~= "\0"; > > image = SDL_LoadBMP( cast(char*)path ); > > > > } > > > > and the value of path is "./resources/cannon.bmp" > > > > I'm using SDL 1.2.14 and DMD 1.067 on Ubuntu 10.10 > > Well strings are put into read-only space on Linux and I guess this is > also the case for D1. > Since you are doing a ~= it probably tries to alter that value and crashes. No. If it can't concatenate in place, then it will reallocate the array. The fact that it was in read-only memory is irrelevant. It just means that reallocation is guaranteed instead of being only possible. - Jonathan M Davis
Re: Help passing D strings to C libs
I'm having trouble passing D strings (char[]) to SDL, in particular SDL_LoadBMP(), I keep receiving a segfault. Heres the code: void setImg(string path) { // concat null terminating char to string and cast to c type string when // passing to SDL_LoadBMP() path ~= "\0"; image = SDL_LoadBMP( cast(char*)path ); } and the value of path is "./resources/cannon.bmp" I'm using SDL 1.2.14 and DMD 1.067 on Ubuntu 10.10 Well strings are put into read-only space on Linux and I guess this is also the case for D1. Since you are doing a ~= it probably tries to alter that value and crashes. You should use something like SDL_LoadBMP(cast(char*)(path ~ "\0")) if you really wanted to convert it manually. But the proper way to convert a string to a C char* is to use toStringz.
Re: Iterating over an enum associative array
I am back. Nebster: > I'm having some problems iterating over an enumerated associative array. > It comes up with this error at compile time: > > Internal error: e2ir.c 4835 Added: http://d.puremagic.com/issues/show_bug.cgi?id=5734 Bye, bearophile
Re: Iterating over an enum associative array
On 14/03/2011 14:38, Peter Lundgren wrote: == Quote from Nebster (evil.nebs...@gmail.com)'s article Hey, I'm having some problems iterating over an enumerated associative array. It comes up with this error at compile time: > Internal error: e2ir.c 4835 I cut the code down to this: > import std.stdio; > > enum int[string] assoc = [";": 0, "=": 1, "+": 2, "-": 2, "*": 3, "/": 3]; > > void main() > { > foreach(op; assoc.byKey()) > writefln("op: %s", op); > } What does this mean/how can I get this to work? Thanks, Nebster That's a rather cryptic error message. Hopefully someone smarter than I can trace down why this doesn't have better error reporting. I suspect the problem has something to do with CTFE. Because you're using an enum, D assumes you want its value to be computed at compile time. However, currently, associative arrays can not be evaluated at compile time. Using a static this to initialize the value at runtime, as already suggested, should solve your issue. That's not the cryptic part, its the name of the source file and line number, its tripping up here: AssocArrayLiteralExp::toElem //... Type *t = type->toBasetype()->mutableOf(); assert(t->ty == Taarray);//line 4835 Though to me that whole function looks like a pile of random abbreviations.
Re: Iterating over an enum associative array
== Quote from Nebster (evil.nebs...@gmail.com)'s article > Hey, > I'm having some problems iterating over an enumerated associative array. > It comes up with this error at compile time: > > Internal error: e2ir.c 4835 > I cut the code down to this: > > import std.stdio; > > > > enum int[string] assoc = [";": 0, "=": 1, "+": 2, "-": 2, "*": 3, > "/": 3]; > > > > void main() > > { > >foreach(op; assoc.byKey()) > >writefln("op: %s", op); > > } > What does this mean/how can I get this to work? > Thanks, > Nebster That's a rather cryptic error message. Hopefully someone smarter than I can trace down why this doesn't have better error reporting. I suspect the problem has something to do with CTFE. Because you're using an enum, D assumes you want its value to be computed at compile time. However, currently, associative arrays can not be evaluated at compile time. Using a static this to initialize the value at runtime, as already suggested, should solve your issue.
Re: I seem to be able to crash writefln
On Fri, 11 Mar 2011 18:57:32 -0500, Spacen Jasset wrote: On 10/03/2011 12:18, Steven Schveighoffer wrote: On Wed, 09 Mar 2011 18:19:55 -0500, Joel Christensen wrote: This is on Windows 7. Using a def file to stop the terminal window coming up. win.def EXETYPE NT SUBSYSTEM WINDOWS bug.d import std.stdio; import std.string; void main() { auto f = File( "z.txt", "w" ); scope( exit ) f.close; string foo = "bar"; foreach( n; 0 .. 10 ) { writefln( "%s", foo ); f.write( format( "count duck-u-lar: %s\n", n ) ); } } output (from in z.txt): count duck-u-lar: 0 If I dust off my rusty old Windows hat, I believe if you try to write to stdout while there is no console window, you will encounter an error. So don't do that ;) I'm not sure what you were expecting... -Steve You normally get no output AFAIR using c++ type compiled programs with printf or cout -- and perhaps an error set in cout, but I can't remember about that now. But don't forget, D uses DMC's runtime, not Visual Studio. Make sure you are comparing to DMC compiled programs. -Steve
Re: Read file/stream
On Fri, 11 Mar 2011 17:39:43 -0500, Stewart Gordon wrote: On 11/03/2011 21:51, Steven Schveighoffer wrote: Presumably there's a reason that it's been provided for uint but not ushort or ulong I think things in std.intrinsic are functions that tie directly to CPU features, True, but... so presumably, the CPU only provides the possibility for 4-byte width. D is designed to run on a variety of CPUs. Do you really think that they all have a built-in instruction to reverse the order of 4 bytes but no other number? No, but if the CPU does not support it, the compiler must simulate it for that platform. I don't know the reasoning behind only supporting 4 bytes, but I'm sure it has something to do with IP addresses being 4 bytes that probably makes CPUs support that specific length more prevalently. I suspect the decision to create an intrinsic or just a regular function is highly subjective (i.e. how many CPUs must support an optimized version in order to make it an intrinsic), so you'd have to ask Walter why it's not in there. -Steve
Re: Iterating over an enum associative array
On 03/14/2011 12:21 PM, Nebster wrote: Hey, I'm having some problems iterating over an enumerated associative array. It comes up with this error at compile time: Internal error: e2ir.c 4835 I cut the code down to this: import std.stdio; enum int[string] assoc = [";": 0, "=": 1, "+": 2, "-": 2, "*": 3, "/": 3]; void main() { foreach(op; assoc.byKey()) writefln("op: %s", op); } What does this mean/how can I get this to work? There are problems with associative array constants. I'm not 100% sure this is the source of your error, though. Anyway, the following works fine, using the module's "static this" constructor: static int[string] assoc; static this () { assoc = [";": 0, "=": 1, "+": 2, "-": 2, "*": 3, "/": 3]; } static enum seq = [1,2,3]; unittest { foreach(op ; assoc.byKey()) writefln("op: %s", op); foreach(n ; seq) writefln("n: %s", n); } ==> op: * op: + op: - op: / op: ; op: = n: 1 n: 2 n: 3 You can use this trick each time you need a D module to hold predefined and/or precomputed data (meaning, you need D to play the role of a data description language). This is not needed if said data is plain simple literal values. As you see, dmd does not consider an associative array to be plain simple literal, even when it obviously is; but a sequential array, yes. A side note: constant struct data can be directly defined at the module top-level, at least in simple cases. But (for any reason), dmd in fact does not create a single constant value that will be used everywhere you write its name. Instead, it re-creates the constant value at each place you write it. Aside the possible cost (?), this can create bugs if you count on it be unique: struct S { int i; } enum S* ps0 = &(S(0)), ps1 = &(S(1)); unittest { S* ps; if (true) ps = ps0; else ps= ps1; assert (*ps == *ps0); // indeed //~ assert (ps == ps0); // fail !!! writefln("%s != %s", ps,ps0); // BFC95FE4 != BFC95FF0 } The trick of using the module's static this clause also solves this issue. Denis -- _ vita es estrany spir.wikidot.com
Iterating over an enum associative array
Hey, I'm having some problems iterating over an enumerated associative array. It comes up with this error at compile time: > Internal error: e2ir.c 4835 I cut the code down to this: > import std.stdio; > > enum int[string] assoc = [";": 0, "=": 1, "+": 2, "-": 2, "*": 3, "/": 3]; > > void main() > { >foreach(op; assoc.byKey()) >writefln("op: %s", op); > } What does this mean/how can I get this to work? Thanks, Nebster
Re: "Semi-const" methods?
On 2011-03-14 00:17:18 +0100, Jonathan M Davis said: So, if you don't actually manage to _really_ be logically const, or if you do this with an immutable object (which would likely result in a segfault), you _are_ going to have incorrect code. On the whole, I'd advise just not using const when you need logical const, but if you're _very_ careful, you can get away with it. But thanks to immutable, it can be _very_ dangerous to cast away constness in a const function unless you're _very_ careful. You really should check out this question on stackoverflow and the answers that go with it: http://stackoverflow.com/questions/4219600/logical-const-in-d Thanks for the insights + tip :) -- Magnus Lie Hetland http://hetland.org
Re: "Semi-const" methods?
On 2011-03-14 11:51:09 +0100, Mafi said: I found away which doesn't use casts or bugs. Just use delegates/closures. Nice :D -- Magnus Lie Hetland http://hetland.org
Re: Read file/stream
On Fri, 11 Mar 2011 22:39:43 -, Stewart Gordon wrote: On 11/03/2011 21:51, Steven Schveighoffer wrote: Presumably there's a reason that it's been provided for uint but not ushort or ulong I think things in std.intrinsic are functions that tie directly to CPU features, True, but... so presumably, the CPU only provides the possibility for 4-byte width. D is designed to run on a variety of CPUs. Do you really think that they all have a built-in instruction to reverse the order of 4 bytes but no other number? I have some in the cryptographic hash modules which I am trying to tidy up for inclusion into phobos. They make use of bswap where possible but otherwise have to do things the long way. It would be nice to have some in std.intrinsic for 16, and 64 bit entities. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Re: "Semi-const" methods?
Am 13.03.2011 23:27, schrieb Magnus Lie Hetland: I have a data structure that's generally static (const, or even immutable), but it has some utility storage, which caches certain results during use. This caching etc. doesn't really affect the semantics of the main object, and are reset between operations, so I think it still would be useful to declare (and statically check) that certain methods don't modify any of the *rest* of the structure (i.e., the "main parts"). I *could* declare the methods const, and pass in a second object (a non-const parameter) for the caching etc. Or I cast the relevant parts to const (assigning them to local variables) early on in the relevant methods (dropping the const modifier on the method itself -- sort of a bummer). Any other ideas on how to handle this sort of "mostly const" or "const where it counts" stuff? Perhaps my design intentions here are off to begin with?-) I found away which doesn't use casts or bugs. Just use delegates/closures. class C { int i; int delegate(int) getCache; this(int fi) { this.i = fi; int lastX, lastR; this.getCache = (int x) { if(x == lastX) return lastR; lastX = x; lastR = x * i; return lastR; }; } const multiply(int x) { return getCache(x); } }
Re: Help passing D strings to C libs
On 03/14/2011 07:55 AM, Gene P. Cross wrote: -Daniel I tried what you said: char* ptr = toStringz(path); SDL_LoadBMP(ptr); and made a check to see if the pointer is null, which it isn't, but I'm unable to inspect is value, I haven't a debugger at the moment, could you recommend one ? I also made the string a char[] and tested to see if that made a difference. I think it may be something to do with SDL itself. I tried calling another function, SDL_GetTicks(), and that's causing problems as well. -Jonathan I read the docs earlier and found the same thing about literals being null terminated but not regular strings, which explains why they work. Double check after double check, I am also certain that no other code is messing with it and changing values. I'm surprised about your problem. There is no difference between the .ptr property of a null-terminated D char[] and a C "string" (hum). And I'm rather sure (not checked the code) that's precisely what toStringZ does. The issue must lie on some point you have not mentionned yet. Denis -- _ vita es estrany spir.wikidot.com
Re: Help passing D strings to C libs
Thanks for your help, and from here on in I'll be sure to initialise first thing. I'll look into GDB, thanks again.
Re: Help passing D strings to C libs
On Monday 14 March 2011 00:07:05 Gene P. Cross wrote: > I found the problem. > > I've set up my 'main' file to act on various game states and because my > load state is physically below the running state (where the problems were > occuring), even though they were getting called first, the program starts > in the loading state, dmd wasn't having it. I tried moving the load state > above the rest, and it works fine. So sorry to have wasted everybody's > time with such a simple and stupid mistake. Thankyou for all your help. It happens to us all from time to time. At least you found the problem. - Jonathan M Davis
Re: Help passing D strings to C libs
On 3/14/2011 3:07 AM, Gene P. Cross wrote: I found the problem. I've set up my 'main' file to act on various game states and because my load state is physically below the running state (where the problems were occuring), even though they were getting called first, the program starts in the loading state, dmd wasn't having it. I tried moving the load state above the rest, and it works fine. So sorry to have wasted everybody's time with such a simple and stupid mistake. Thankyou for all your help. That sounds like an issue, I've ran into on occasion. When using runtime bindings for shared libraries. If you forget to initialize them in every module first thing. The program will segfault.
Re: Help passing D strings to C libs
On 3/14/2011 2:55 AM, Gene P. Cross wrote: I haven't a debugger at the moment, could you recommend one ? Sorry, I use GDB with GDC. I don't know about DMD, it may work with GDB on linux. You could try installing GDC and see if the results are the same. That may help to rule out the compiler itself. I also made the string a char[] and tested to see if that made a difference. That also requires using some of the previous examples to append '\0' first. I think it may be something to do with SDL itself. I tried calling another function, SDL_GetTicks(), and that's causing problems as well. Can you install a program that uses SDL and are you running 64-bit? Could be possible you're trying to call a 64-bit function from 32-bit code. I read the docs earlier and found the same thing about literals being null terminated but not regular strings, Every suggestion so far should take care of that issue.
Re: Help passing D strings to C libs
I found the problem. I've set up my 'main' file to act on various game states and because my load state is physically below the running state (where the problems were occuring), even though they were getting called first, the program starts in the loading state, dmd wasn't having it. I tried moving the load state above the rest, and it works fine. So sorry to have wasted everybody's time with such a simple and stupid mistake. Thankyou for all your help.