Re: really why module declarations?
On Sunday, March 26, 2017 20:51:01 XavierAP via Digitalmars-d-learn wrote: > I've perused both the spec[1] and Andrei's book, and I the idea I > get is that module declarations are optional, recommended only in > case of file names not being valid D names. But in the community > (and Phobos) I see it's strongly recommended and used throughout. > > What's the reason? If the declaration overrides the path > (provided the file is found) rather than enforcing path > consistency by outputting a compile error, then what's the > benefit of module declarations, if we have to be disciplined to > keep it consistent with paths anyway? > > I'm busy starting my first big multi file D project, thanks for > any feedback! > > > [1] https://dlang.org/spec/module.html#ModuleDeclaration What it really comes down to is that if you don't give the module name, the compiler infers it, and it doesn't infer packages. So, if you have foo/bar.d where bar.d's contents are == void main() { pragma(msg, __MODULE__); } == and you compile with dmd foo/bar.d, you're going to see bar printed, whereas if you have == module foo.bar void main() { pragma(msg, __MODULE__); } == then you'll see foo.bar printed. So, if all you're ever doing is one file programs, then it really doesn't matter, but if you're doing anything with packages, you have to use module declarations. You also have to use them if you want to document a module. As for "overiding" the path... the compiler and other tools use the module path as the path on disk to look for the files - e.g. if you tell the compiler that /usr/local/include/dlang/ is an import directory, it'll start looking for modules in there, and if it's looking for foo.bar, that means that it's looking for /usr/local/include/dlang/foo/bar.d. On some level, it is possible to give a module name or package name that doesn't match the exact file or folder names on disk, but really, that's just asking for trouble. It'll work in some basic cases, but it'll fall flat on its face in real projects. rdmd goes a step further and will compile additional modules based on what's imported (i.e. if a module is imported but wasn't previously compiled, it'll compile it), and when a tool does something like that, it makes it that much worse if your module path isn't equivalent to the path on disk. - Jonathan M Davis
Re: how to define my own traits
On Sunday, 26 March 2017 at 23:25:49 UTC, XavierAP wrote: I've looked into Phobos to emulate it when defining my own trait template, and when I see this: module std.range.primitives; // ... template isInputRange(R) { enum bool isInputRange = is(typeof( (inout int = 0) { R r = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront; // can invoke popFront() auto h = r.front; // can get the front of the range })); I wonder, why that unused parameter (inout int = 0)? `git blame` is your friend. It's all documented in the commit logs: The original version does not have that parameter [1]. Then, to fix using isInputRange on an inout argument [2] a dummy parameter was introduced to force the delegate inside isInputRange to be typed as inout as well [3]. Later, the dummy parameter's name was dropped [4]. In my project () { /* ... */ } works the same for a custom trait. Have you tried it without the dummy parameter on the example given in the bug report [2]? [1] https://github.com/dlang/phobos/commit/49f646271bf6c843fcdd90249baa875bf43be0a1#diff-b7fc67b6fcb7d1a521918d06ffe03587R50 [2] https://issues.dlang.org/show_bug.cgi?id=7824 [3] https://github.com/dlang/phobos/commit/ed00f6c28c602bd5c3b197e555c44d3b53ef76ba [4] https://github.com/dlang/phobos/commit/db1d909d7adb1b28ec0ba1895f56da0cc01a937b
how to define my own traits
I've looked into Phobos to emulate it when defining my own trait template, and when I see this: module std.range.primitives; // ... template isInputRange(R) { enum bool isInputRange = is(typeof( (inout int = 0) { R r = R.init; // can define a range object if (r.empty) {} // can test for empty r.popFront; // can invoke popFront() auto h = r.front; // can get the front of the range })); I wonder, why that unused parameter (inout int = 0)? In my project () { /* ... */ } works the same for a custom trait.
Re: really why module declarations?
On Sunday, 26 March 2017 at 20:51:01 UTC, XavierAP wrote: I've perused both the spec[1] and Andrei's book, and I the idea I get is that module declarations are optional, recommended only in case of file names not being valid D names. But in the community (and Phobos) I see it's strongly recommended and used throughout. What's the reason? If the declaration overrides the path (provided the file is found) rather than enforcing path consistency by outputting a compile error, then what's the benefit of module declarations, if we have to be disciplined to keep it consistent with paths anyway? I'm busy starting my first big multi file D project, thanks for any feedback! [1] https://dlang.org/spec/module.html#ModuleDeclaration In addition to what Adam has said, they allow you to treat the module as a symbol during compilation. You _can_ do that with the implicitly generated one, but you can't do things that requires the declared symbol, e.g. attach UDAs which is how dcompute distinguishes device modules from host modules and possibly reflect of the symbols (although you can use __MODULE__ for that).
Re: really why module declarations?
On Sunday, 26 March 2017 at 22:10:07 UTC, XavierAP wrote: I was curious but I guess it's long to explain the different things that can go wrong if one doesn't declare module names. You'll just get a name conflict eventually. Either two modules with the same name, or "module `foo` must be imported as `foo.bar`" errors when stuff fails to line up, then you'll need to go in and change all the imports to fix it. Real hassle to do later, real easy to do now. Followup question: if I am inside module myproj.pack1.mod1 and want to import myproj.pack1.mod2... should I import myproj.pack1.mod2; or import mod2; ? Always use the full module name in import. If you want to abbreviate it, do module something = myproj.pack.mod2; then you can refer to it as `something` throughout the usage points in that file.
Re: really why module declarations?
On Sunday, 26 March 2017 at 20:58:24 UTC, Adam D. Ruppe wrote: Module declarations are only optional in the most trivial case that is rarely useful in real world code. I recommend you ALWAYS use them (and always put a ddoc comment on them!), and moreover that you avoid top name modules (use `myproject.modname` instead of `modname`) to avoid conflicts. OK I was already doing it all this in the multi-file project. I was curious but I guess it's long to explain the different things that can go wrong if one doesn't declare module names. Followup question: if I am inside module myproj.pack1.mod1 and want to import myproj.pack1.mod2... should I import myproj.pack1.mod2; or import mod2; ?
Re: Howto catch SocketOSException?
On Sunday, 26 March 2017 at 18:50:13 UTC, bauss wrote: On Sunday, 26 March 2017 at 11:46:39 UTC, Jolly James wrote: [...] Chances are it's invoked in another thread and thus you can't catch it like that. To sum it up. Ex. void thisFunctionThrows() { ... } void ableToCatch() { try { thisFunctionThrows(); } catch (Exception e) { // We can catch the exception ... } } void notAbleToCatch() { try { spawn(&thisFunctionThrows); } catch (Exception e) { // We cannot catch the exception ... } } void ableToCatchToo() { spawn(&ableToCatch); // We're able to handle the exception, because the try/catch is handled in the thread that calls the function that throws. } If you want try to help me, mabye this helps you: https://github.com/CyberShadow/ae/blob/master/net/asockets.d#L1237
Re: Loading assimp
On 03/26/2017 11:31 PM, Dlearner wrote: SDL_Surface* surface = IMG_Load(filename.ptr); if (surface is null) { writeln("surface is null: ", to!string(IMG_GetError())); } else { writeln(filename); } From console: surface is null: Couldn't open Models/Nanosuit/helmet_diff.pngÇ2ÿ I'm assuming the previous textures didn't experience this, but I have no idea what could be the problem here, especially as the filename seems fine when I writeln it. :( How do you construct `filename`? Looks like it's not properly null-terminated. If you followed my (short-sighted) `dup` advice, that doesn't do null-termination. Since the original strings are null-terminated, just slicing one more character should do the trick. I'd put an assert that verifies that the last character is '\0'. I.e.: string z = x.data[0 .. x.length + 1].idup; assert(z[$ - 1] == '\0'); Generally, don't pass just the pointer of a string unless you know for sure that it's properly null-terminated. If you're using a slice directly, without `dup`-ing, then the original aiString would seem to be broken already.
Re: Loading assimp
On Sunday, 26 March 2017 at 12:40:42 UTC, Dlearner wrote: ... About half the textures seem to load fine. Some progress! I don't know why, but when I get to the 8th texture, the filename has some garbage attached. SDL_Surface* surface = IMG_Load(filename.ptr); if (surface is null) { writeln("surface is null: ", to!string(IMG_GetError())); } else { writeln(filename); } From console: surface is null: Couldn't open Models/Nanosuit/helmet_diff.pngÇ2ÿ I'm assuming the previous textures didn't experience this, but I have no idea what could be the problem here, especially as the filename seems fine when I writeln it. :(
Re: really why module declarations?
On Sunday, 26 March 2017 at 20:51:01 UTC, XavierAP wrote: I've perused both the spec[1] and Andrei's book, and I the idea I get is that module declarations are optional, recommended only in case of file names not being valid D names. Module declarations are only optional in the most trivial case that is rarely useful in real world code. I recommend you ALWAYS use them (and always put a ddoc comment on them!), and moreover that you avoid top name modules (use `myproject.modname` instead of `modname`) to avoid conflicts. If you don't, you are depending on implicit magic and just hoping that there's no conflict from third party libraries, and those lead to problems, almost guaranteed before long. if we have to be disciplined to keep it consistent with paths anyway? That's false, the path is irrelevant to the D language, ONLY the module declaration gives the canonical name. The path is just a helper for automatic tools to find the module given an import, but my preference is to ditch those things and actually just list your modules by name anyway. Then everything works reliably and consistently.
really why module declarations?
I've perused both the spec[1] and Andrei's book, and I the idea I get is that module declarations are optional, recommended only in case of file names not being valid D names. But in the community (and Phobos) I see it's strongly recommended and used throughout. What's the reason? If the declaration overrides the path (provided the file is found) rather than enforcing path consistency by outputting a compile error, then what's the benefit of module declarations, if we have to be disciplined to keep it consistent with paths anyway? I'm busy starting my first big multi file D project, thanks for any feedback! [1] https://dlang.org/spec/module.html#ModuleDeclaration
Re: Howto catch SocketOSException?
On Sunday, 26 March 2017 at 11:46:39 UTC, Jolly James wrote: On Sunday, 26 March 2017 at 11:35:00 UTC, Jolly James wrote: [...] Found out something: You cannot catch any exception thrown in the listen()-method in general. ■ Original code: [...] ■ Modified one: [...] ■ Not working try-catch: [...] Chances are it's invoked in another thread and thus you can't catch it like that. To sum it up. Ex. void thisFunctionThrows() { ... } void ableToCatch() { try { thisFunctionThrows(); } catch (Exception e) { // We can catch the exception ... } } void notAbleToCatch() { try { spawn(&thisFunctionThrows); } catch (Exception e) { // We cannot catch the exception ... } } void ableToCatchToo() { spawn(&ableToCatch); // We're able to handle the exception, because the try/catch is handled in the thread that calls the function that throws. }
Re: Loading assimp
On Sunday, 26 March 2017 at 11:10:55 UTC, ag0aep6g wrote: On Sunday, 26 March 2017 at 10:34:21 UTC, Dlearner wrote: I came back to this project and realised my mistakes (Importer is a class for the C++ API, and we're using the C API). So I fixed all my errors, but now I get an access violation. As far as I can tell, it seems to be an issue with `aiGetMaterialTexture`. It is meant to return an aiString with a filename (default value of "$texture.png"), I believe. But I get: aiString(13, x"67 6C 61 73 73 5F 64 69 66 2E 70 6E 67 00 FF FF FF ... FF"c) [shortened for brevity] The data is "glass_dif.png", followed by a null terminator, followed by a bunch of 0xFFs. 13 is the length of "glass_dif.png". Judging from the definition of aiString [1], the 0xFFs are just unused space. So, this looks good. I'm meant to add this on to a directory string so I can load an image, but obviously this wouldn't work. To convert an aiString to a D string, it should be possible to slice the data with the length: aiString x; const(char)[] y = x.data[0 .. x.length]; You have to be cautiots of lifetime requirements, of course. If needed, you can make a copy with dup (mutable copy) or idup (immutable copy): const(char)[] y = x.data[0 .. x.length].dup; string z = x.data[0 .. x.length].idup; [1] http://www.assimp.org/lib_html/structai_string.html Ahh this did help! I practically followed your advice, then fixed a somewhat unrelated range violation, and got a similar "object.Error@(0): Access Violation". But in the console I got: filename: Models/Nanosuit/glass_dif.png filename: Models/Nanosuit/leg_dif.png filename: Models/Nanosuit/leg_showroom_spec.png filename: Models/Nanosuit/hand_dif.png filename: Models/Nanosuit/hand_showroom_spec.png filename: Models/Nanosuit/arm_dif.png filename: Models/Nanosuit/arm_showroom_spec.png filename: Models/Nanosuit/helmet_diff.png About half the textures seem to load fine. Some progress!
Re: Howto catch SocketOSException?
On Sunday, 26 March 2017 at 11:35:00 UTC, Jolly James wrote: On Sunday, 26 March 2017 at 02:41:46 UTC, Adam D. Ruppe wrote: On Sunday, 26 March 2017 at 02:24:56 UTC, Jolly James wrote: You can ignore the loop()-method. It is not called as the application will never reach this statement, because it cannot, because it crashes already in the listen()-method in consequence of the exception that does not get caught by the try-catch block. Try putting it in the try anyway and see what happens. It is an async socket library, they can do weird things.\ Unfortunately not working either. I should not forget to mention that the exception also raises when the code does not contain the loop()-call. Found out something: You cannot catch any exception thrown in the listen()-method in general. ■ Original code: auto addressInfos = getAddressInfo(addr, to!string(port), AddressInfoFlags.PASSIVE, SocketType.STREAM, ProtocolType.TCP); ■ Modified one: AddressInfo[] addressInfos; try { addressInfos = getAddressInfo(addr, to!string(port), AddressInfoFlags.PASSIVE, SocketType.STREAM, ProtocolType.TCP); } catch(SocketOSException e) { throw new Exception("Invalid address: " ~ addr, e); } ■ Not working try-catch: try { tcp.listen(2345, "127.0.0.1c"); socketManager.loop(); } catch (Exception e) { return; }
Re: Howto catch SocketOSException?
On Sunday, 26 March 2017 at 02:41:46 UTC, Adam D. Ruppe wrote: On Sunday, 26 March 2017 at 02:24:56 UTC, Jolly James wrote: You can ignore the loop()-method. It is not called as the application will never reach this statement, because it cannot, because it crashes already in the listen()-method in consequence of the exception that does not get caught by the try-catch block. Try putting it in the try anyway and see what happens. It is an async socket library, they can do weird things.\ Unfortunately not working either. I should not forget to mention that the exception also raises when the code does not contain the loop()-call.
Re: Loading assimp
On Sunday, 26 March 2017 at 10:34:21 UTC, Dlearner wrote: I came back to this project and realised my mistakes (Importer is a class for the C++ API, and we're using the C API). So I fixed all my errors, but now I get an access violation. As far as I can tell, it seems to be an issue with `aiGetMaterialTexture`. It is meant to return an aiString with a filename (default value of "$texture.png"), I believe. But I get: aiString(13, x"67 6C 61 73 73 5F 64 69 66 2E 70 6E 67 00 FF FF FF ... FF"c) [shortened for brevity] The data is "glass_dif.png", followed by a null terminator, followed by a bunch of 0xFFs. 13 is the length of "glass_dif.png". Judging from the definition of aiString [1], the 0xFFs are just unused space. So, this looks good. I'm meant to add this on to a directory string so I can load an image, but obviously this wouldn't work. To convert an aiString to a D string, it should be possible to slice the data with the length: aiString x; const(char)[] y = x.data[0 .. x.length]; You have to be cautiots of lifetime requirements, of course. If needed, you can make a copy with dup (mutable copy) or idup (immutable copy): const(char)[] y = x.data[0 .. x.length].dup; string z = x.data[0 .. x.length].idup; [1] http://www.assimp.org/lib_html/structai_string.html
Re: Loading assimp
I came back to this project and realised my mistakes (Importer is a class for the C++ API, and we're using the C API). So I fixed all my errors, but now I get an access violation. As far as I can tell, it seems to be an issue with `aiGetMaterialTexture`. It is meant to return an aiString with a filename (default value of "$texture.png"), I believe. But I get: aiString(13, x"67 6C 61 73 73 5F 64 69 66 2E 70 6E 67 00 FF FF FF ... FF"c) [shortened for brevity] I'm meant to add this on to a directory string so I can load an image, but obviously this wouldn't work. I thought it might be a problem with converting from D-strings to C-strings. I sent a string to `aiImportFile` as `toStringz(path)`. I tested this with some writeln debugging: ``` auto temp = path.toStringz; writeln("toStringz: ", temp); writeln("string: ", temp.to!string); ``` This gave: toStringz: 4770B6 string: Models/Nanosuit/nanosuit.obj So maybe this is a problem with using aiStrings? I'm quite confused. Sorry if this is more of an assimp question than a D question, but I don't know if it's me misusing D language features or not.
Re: union.sizeof
On Sunday, 26 March 2017 at 07:18:14 UTC, ketmar wrote: i.e. what compiler does (roughly) is inserting anonymous fields of the appropriate size *into* the container. for "inner" aligning compiler inserts anonymous fields *between* other fields. for "outer" aligning compiler just appends anonymous field at the *end* of a data type, so data type size will met align requirements. Big thank!!
Re: union.sizeof
zabruk70 wrote: On Sunday, 26 March 2017 at 06:45:13 UTC, ketmar wrote: yes. you have a typo in second `writefln`: S1 instead of S2. ;-) thank you. another question, related to my first post: why size of S2.b1 and S2.b2 still 3, not 4? am i right: then align applied to members, compiler not change size of members, just make padding, so CONTAINER size changes? yes. compiler is not allowed to mess with data types of the known size. ;-) and you are right: it doesn't have to. it just inserts dummy anonymous (and unused) bytes into struct/union to satisfy alignment requirements. if so (because size of S2.b1 and S2.b2 still is 3 in my code), then adding align(1) outside of union must not change zise of union, but size of some comainer more upper level. nope, it changes size of the union itself. padding bytes *are* included in union, so `myunion.sizeof` includes 'em too. i.e. what compiler does (roughly) is inserting anonymous fields of the appropriate size *into* the container. for "inner" aligning compiler inserts anonymous fields *between* other fields. for "outer" aligning compiler just appends anonymous field at the *end* of a data type, so data type size will met align requirements.
Re: foreach, is and pointer
On 26/03/2017 7:52 AM, helxi wrote: What's the difference between 1. string x = "abcd"; foreach(character; x) write(character); and string x = "abcd"; foreach(character; x[0..$]) write(character); Hopefully the compiler is smart enough to ignore that slice (since its identical in purpose). 2. is and == is: bit for bit comparison ==: "magic" comparison logic, supports e.g. opEquals on classes. 3. pointer and address and reference? pointer: a place in memory! or hdd.. or well pretty much anywhere the kernel maps it to, just assume that there is some data there that you may be able to do some, all or none of these things read, write, execute. May also be invalid aka null aka 0. reference: pointer + some other pointer generally, e.g. class instance data pointer + typeinfo reference + vtable.