Re: pipeProcess not returning immediately
On Saturday, 26 August 2017 at 06:24:26 UTC, user1234 wrote: On Saturday, 26 August 2017 at 01:13:35 UTC, Johnson Jones wrote: I am running ffplay.exe and my application does not return immediately from pipeProcess. I have to close ffplay for my program to continue execution. No process is asynchronous in std.process. If you don't want to block your program then wrap it in a thread that checks periodically for termination. Either you are wrong or the docks are wrong: https://dlang.org/phobos/std_process.html pipeProcess also spawns a child process which runs in **parallel** with its parent. However, instead of taking arbitrary streams, it automatically creates a set of pipes that allow the parent to communicate with the child through the child's standard input, output, and/or error streams. This function corresponds roughly to C's popen function.
Re: gtkD: events being triggered twice
On Sunday, 6 August 2017 at 18:26:20 UTC, Mike Wey wrote: On 06-08-17 16:58, FoxyBrown wrote: I don't really(my code is a bit more complex) but basically all it boils down to is a UI with some nested widgets (an overlay, an box, and a box and one contains the eventbox which I added those callbacks on. I think that something like https://github.com/gtkd-developers/GtkD/blob/master/demos/gtkD/TestWindow/TestWindow.d should probably work by just adding an eventbox somewhere and adding that code above. If it doesn't exhibit the same behavior then it has something to do with my project and I could try to reduce it to a minimal example. To test i put the label that is on the label page in an event box but that doesn't reproduce the issue. I get just a single event on enter and a single event on leave. Ok, I will try to work on figuring out what is going and and potentially reduce to a test case. It might be on my end. I'm pretty sure I'm not adding You might try a separator though in the event box and might try to add it handling various events(maybe even other events for the event box)... things related to the mouse. Here's the glade code for the event box I'm using 5 True False True 5 True False False name="orientation">vertical Try that when you get some time and see if that changes anything. If it doesn't then it's surely in my code or in the gtk version I'm using(still using msys, I'll update to what you released to see if that fixes it). At least we can narrow it down a little...
Re: gtkD: events being triggered twice
On Sunday, 6 August 2017 at 09:42:03 UTC, Mike Wey wrote: On 06-08-17 03:25, Johnson Jones wrote: GtkEventBox - Enter GtkEventBox - Enter Down GtkEventBox - Leave Up GtkEventBox - Leave GtkEventBox - Leave That is when I move the mouse over the event box then click then move out out then release. I would expect Enter Down Leave Up The fact that enter and leave are not paired equally is a problem. Can be worked around but seems like it would be a bug. the code is simply ebox.addOnEnterNotify(delegate(Event e, Widget w) { writeln(w.getName(), " - ", "Enter"); return true;}); ebox.addOnLeaveNotify((Event e, Widget w) {writeln(w.getName(), " - ", "Leave"); return true; }); Do you have an more complete example that i could test. I don't really(my code is a bit more complex) but basically all it boils down to is a UI with some nested widgets (an overlay, an box, and a box and one contains the eventbox which I added those callbacks on. I think that something like https://github.com/gtkd-developers/GtkD/blob/master/demos/gtkD/TestWindow/TestWindow.d should probably work by just adding an eventbox somewhere and adding that code above. If it doesn't exhibit the same behavior then it has something to do with my project and I could try to reduce it to a minimal example.
Re: Visual D no bp's on x64
On Sunday, 6 August 2017 at 03:12:22 UTC, FoxyBrown wrote: On Thursday, 3 August 2017 at 20:22:56 UTC, Johnson Jones wrote: On Thursday, 3 August 2017 at 07:06:06 UTC, Rainer Schuetze wrote: [...] Thanks! Seems to be working. well, in x86 I still get a few BP's that won't be hit every once in a while(well, happened for the first time since I've used the new release). The code looks like while(i < data.length && data[i] != '>' && data[i] != '"' && data[i..i+token2.length] != token2) i++; if (data[i] == '>') { continue; } I put a BP on the if and when ran it says it won't be hit. I have a BP right above it and below it and it works fine. says "The BP will not currently be hit. No symbols have been loaded for this document.". I do not know why symbols really matter for BP's? If I change the if statement to if (data[i] == '>') { continue; } it works ;/ Oops, it "works". The BP icon is no longer a hollow read disk but it is simply not hit ;/ I know all this doesn't help much but it all seems to be related to the previous bugs.
Re: Create class on stack
On Sunday, 6 August 2017 at 02:32:05 UTC, Adam D. Ruppe wrote: On Sunday, 6 August 2017 at 02:19:19 UTC, FoxyBrown wrote: Also, does it do the allocation at compile time(reserve space on the stack for the variable along with all the others or does it "allocate" space on the stack at runtime?... which is slightly slower). compile time. It works like a static array of the appropriate size. though the cost if ti was at runtime is small regardless. I think it is just a register subtract. yeah, I know, but no need for it ;) Still better than the heap but was just curious ;) No need to waste cycles if it's not necessary.
Re: Create class on stack
On Sunday, 6 August 2017 at 02:10:31 UTC, Moritz Maxeiner wrote: On Sunday, 6 August 2017 at 01:18:50 UTC, Johnson Jones wrote: On Saturday, 5 August 2017 at 23:09:09 UTC, Moritz Maxeiner wrote: On Saturday, 5 August 2017 at 17:08:32 UTC, Johnson Jones wrote: using gtk, it has a type called value. One has to use it to get the value of stuff but it is a class. Once it is used, one doesn't need it. Ideally I'd like to treat it as a struct since I'm using it in a delegate I would like to minimize unnecessary allocations. Is there any way to get D to allocate a class on the stack like a local struct? The easy way is through std.typecons.scoped [1]. Here be dragons, though, because classes are reference types. [1] https://dlang.org/phobos/std_typecons.html#.scoped Thanks, I didn't think it created on the stack but it makes sense to do so. See the source [1] as to why: typeof(scoped!T) is a (non-copyable) struct that holds the memory for the T object inside it. The only issue is that it escaping the reference? Yes, don't escape references, that's the reason for my comment: Here be dragons, though, because classes are reference types. [1] https://github.com/dlang/phobos/blob/v2.075.0/std/typecons.d#L6613 I don't think you understand what I'm saying. If I use this method to create a "reference" type on the stack rather than the heap, is the only issue worrying about not having that variable be used outside that scope(i.e., have it "escape")? Obviously since it's on the stack it will be invalid after the function call, but I'm talking about other pitfalls. I don't see any but I want to be sure. Also, does it do the allocation at compile time(reserve space on the stack for the variable along with all the others or does it "allocate" space on the stack at runtime?... which is slightly slower).
Re: gtk get actual pixel height of widget
On Saturday, 5 August 2017 at 15:23:15 UTC, Johnson Jones wrote: I am trying to set positions of widgets automatically. e.g., I have a paned widget and I to set the position of the handle manually based on a percentage of the window. e.g., 0.5 will set the handle midway and both children will have the same height. I 0.2 will set it to to 20%. [...] Sorry, I think I was running my code before the window was actually being shown and I guess these values are not set until the actual display of the window.
Re: gtk arch issues
On Tuesday, 1 August 2017 at 21:03:44 UTC, Mike Wey wrote: On 01-08-17 22:16, Johnson Jones wrote: nvm, the file exists. Why it is not being found is unknown. I did some stuff and it says it is not a valid win32, this is using that gtk3 runtime I linked to... says it's x64 version but probably x86. Would be nice if the error message printed the full path of what was being loaded so it's quicker to diagnose. Seems there is a > ... code ... which is used, could I just hijack this to set the correct path based on what version it is compiled under? Would be the easiest thing, at least as a temporary workaround. You renamed the gtk DLL's, i assume you simply renamed them, but to get things working with different names you would need to build GTK from source, and apply the appropriate patches to GTK and its make files. I rebuilt gtkD but obviously not gtk, which I guess was using searching the dll's the same way that gtkD did. If you would use a dependency walker on libgtk-3-0.dll you can see that it depends on basically all the other dll's in the directory, and by renaming them they can no longer be found. For libraries that are in both GTK 3 and GTK 2 it might find the libraries distributed with gtksharp but that would also fail because of the version difference. I didn't actually rename, I copied then renamed the copies so that the originals were still there. The point was to get gtkD to use different versions, which it did, but I guess gtk had the same problem with it's versioning where it would simply try to use whatever it found in the path. Printing the full path of the library in the error would only only be possible if we call LoadLibrary with the full path. It's been a while since i implemented the architecture check but if i remember correctly there were some issues with that. Otherwise it might be loaded from one of the other directories LoadLibrary searches, and then the printed path would be wrong, making things even worse. And yes you could hard code the path that is passed to SetDllDirectory as a work around, but the dll's will need to have there proper names. As I stated the last post, everything is working. I reverted back to the original gtkD so it uses the original names. I only have one GTK dir in the path at a time now rather than both x86 and x64. That solved the problem. The only problem that exists now is that I have to manually swap the installations of gtkx86 and gtkx64. When I switch from from x86 to x64 and vice versa... not difficult but I'm sure I'll forget months down the road and waste time trying to remember what I needed to do. So, I have dirs like C:\Gtkx86 C:\Gtkx64 C:\Gtk where C:\Gtk is a junction that points to either C:\Gtkx86 or C:\Gtkx64 depend on which arch I'm compiling for. The path only as C:\Gtk in it so there is no possibility for the dlls to get mixed up, which is what happens when both architecture versions are in the path. I'd like to avoid having to change the junction each time I decide to test my app in a different architecture. Instead, having a simple version(X86) SetGTKDir("C:\\Gtkx86"); version(Win64) SetGTKDir("C:\\Gtkx64"); is what I'm after.
Re: It makes me sick!
On Saturday, 29 July 2017 at 21:48:09 UTC, Timon Gehr wrote: On 28.07.2017 23:30, FoxyBrown wrote: because you didn't want to spend 10 minutes to fix a program. You need to realize that the same thing applies to you. There is no "us" vs "you". I.e. if you know it to only be 10 minutes of work, why don't you just fix it yourself? Mike currently has as many commits in DMD as you do, and he is already busy contributing in other ways. EXACTLY! Your problem is that you are taking the you vs me too literal. I am talking about a mentality people have that think that them saving 10 minutes by not implementing something that will save 10 hours(low estimate) for everyone else is a good thing and criticize people when they say there is a better and try to condemn them and continue the status quo that wastes more time.
Re: It makes me sick!
On Saturday, 29 July 2017 at 19:51:30 UTC, Adam D. Ruppe wrote: On Saturday, 29 July 2017 at 19:26:03 UTC, FoxyBrown wrote: Also, equating dmd to an audio program or a clip art program that is designed to load any and all files in it's install dir is moronic too. I like to add files to the dmd install directory to expand its "just works" library. I was bitten by this change too. I'm of the opinion that splitting std.datetime was a waste of time and also that the package.d feature is misdesigned. It should ALSO allow any other file to be passed with the module declaration that matches... you know, like every other module in the language. Why it got this bizarre special requirement is beyond me. If it did, then we could easily enough just leave the old file. But no, it requires the new one, but then prolly on efficiency grounds, doesn't check it first meaning the old one can silently conflict. Ugh. But the fix here is to fix the bizarre package.d design. Don't break the zip for cases like mine where adding files is a key feature of it. I don't mind the issue as long as it is stated clearly what must be done(e.g., simply add "requires cleaned installed directory"). What pisses me off more more than anything is the asinine people defending the behavior as if it is acceptable and that it is the users fault to know that the behavior. Many programs I use can be upgraded without issue by copying over the data files. Dmd did not have this program until recently and so, because it isn't stated it is a problem, how the hell is the user suppose to know that? Specially when it worked correct the first time, the second time, the third time, etc.
Re: It makes me sick!
On Saturday, 29 July 2017 at 19:17:08 UTC, Joakim wrote: On Friday, 28 July 2017 at 22:32:27 UTC, FoxyBrown wrote: [...] What you are suggesting is blatantly idiotic. No software ever made supports simply installing on top of an old installation from a compressed zip or tar file. If you need hand-holding, the installer will wipe the old install before unpacking the new install for you. The zip file is for people who know what they are doing, such as not unpacking on top of the old install. You should just use the installer from now on, not the zip file, if you can't be bothered to remove the old install first. bullshit. Are you a moron? You really think your absolute "No software ever" is logical? I can name many off the top of my head. Have you ever heard the fucking word "portable"? I guess not, go look it up. Please take your jack ass arrogant self somewhere else. Also, equating dmd to an audio program or a clip art program that is designed to load any and all files in it's install dir is moronic too.
Re: dmd can't build gtk x64
On Friday, 28 July 2017 at 22:45:58 UTC, FoxyBrown wrote: Error: can't run 'C:\VS\VC\Tools\MSVC\14.10.25017\bin\HostX64\x64', check PATH It is trying to run some x64.exe/com/bat file... why? What is this file? simply doing dmd -m64 build.d Works fine for x86. I was able to get this to work by copying all the required lib's to the lib dir from the windows sdk(liburct.lib, shell32.lib) and copying link.exe to x64. The program compiles, but when ran, I get the error object.Exception@generated\gtkd\gtkd\Loader.d(125): Library load failed (libgdk-3-0.dll): is not a valid Win32 application. which I assume is due to the fact that I have x86 gtk installed(I think, as I thought I installed the dual package... can't seem to find x64 gtk3+ standalone).
Error 1: Previous Definition Different : _D3gtk3All12__ModuleInfoZ (gtk.All.__ModuleInfo)
After upgrading to latest dmd and having to rebuild gtk, I now get the following error Error 1: Previous Definition Different : _D3gtk3All12__ModuleInfoZ (gtk.All.__ModuleInfo) in my apps that were previously working(no changes, opened up old app and tried to build it and it didn't work). All I did was upgrade dmd2. So tired of D and it's crap ;/ So unstable in so many ways. About 10% as productive overall than other languages I've used. It's error messages are about as helpful as a rock.
dmd can't build gtk x64
Error: can't run 'C:\VS\VC\Tools\MSVC\14.10.25017\bin\HostX64\x64', check PATH It is trying to run some x64.exe/com/bat file... why? What is this file? simply doing dmd -m64 build.d Works fine for x86.
Re: It makes me sick!
On Friday, 28 July 2017 at 21:35:01 UTC, Anonymouse wrote: On Friday, 28 July 2017 at 21:23:22 UTC, FoxyBrown wrote: So, the program, if it is updated shouldn't use the mp3's then. Why the hell is the program that you say was upgraded to use the ogg still searching and using mp3's? You are trying to make up reasons why it shouldn't work... at least come up with valid reasons. I'm sorry if I'm not expressing it in a way that agrees with you but you're looking at the wrong side of the example. You're pasting one set of files onto another and expect the software to somehow know to ignore some of them. YES! EXACTLY! I AM EXPECTING THE SOFTWARE, WHICH IS WHAT THE PROGRAMMER CREATED AND HANDLES THE FILES TO ACTUALLY KNOW WHAT THE HELL IT IS DOING! I'm sorry if that is too complex to understand. If the software has some build in design that makes it use arbitrary files in a specific way like it does with std.datetime, then it should have sanity checks. After all, who the hell knows more about dmd using std.datetime and how it uses it and such, the end user or the programmer of dmd? You are expecting the end user, who generally knows very little to do the dirty work instead of having the programmer who is suppose to know what the fuck is going on to add sanity checks, useful error messages, etc. Ali suggested a very reasonable solution that would have solved this problem and you guys are against it and offer no solution to the issue. It all boils down to laziness. Too lazy to spend the time to add code that makes dmd more robust. Simple as that. It's not that it can't be done, like you bone-heads are claiming, but that you simply don't want to do it. Another very simple solution: Before the zip file is generated, a listing of all the files in the dmd installation that are used(which should be all of them) is taken. This file then is parsed by dmd and only those files in the dmd dir that are in the list are used. This would also have avoided the issue and future issues. Any stale files in the dir would simply be ignored. But, again, too much work. Keep making the end users deal with these problems instead of doing your due diligence. That we, we have something to waste our time with in these forums instead of real problems.
Re: It makes me sick!
On Friday, 28 July 2017 at 01:10:03 UTC, Mike Parker wrote: On Friday, 28 July 2017 at 00:28:52 UTC, FoxyBrown wrote: You are not being very logical. The zip file as N files in it. No matter what those files are, it should be a closed system. That is, if I insert or add(not replace) M file to the directory structure it should not break D, period! That's *not* what happened here. Jonathan explained it quite well. std.datetime was refactored into a package, its contents split into new modules. When you import a module foo, dmd looks for: 1. foo.di 2. foo.d 3. foo/package.d When it finds one, it stops looking. It's not an error for all three to exist. Your error came because it found std/datetime.d, but you linked to a library that included symbols for std/datatetime/package.d. It's not the compiler's responsibility to error in that case. It's your responsibility to properly install. Why? Because NO file in the zip should be referencing any file not in the zip unless it is designed to behave that way(e.g., an external lib or whatever). If an old external program is referencing a file in dmd2 that isn't in the new zip it should err. Why? Because suppose you have an old program that references some old file in dmd2 dir and you upgrade dmd2 by extracting the zip. The program MAY still work and use broke functionality that will go undetected but be harmful. Why? Because dmd.exe is reference a file it shouldn't and it should know it shouldn't yet it does so anyways. It really has nothing to do with the file being in the dir but that dmd is being stupid because no one bothered to sanity checks because they are too lazy/think it's irrelevant because it doesn't effect them. That's unreasonable. I should be able to put any extra files anywhere in the dmd2 dir structure and it should NOT break dmd. There are numerous applications out there that can break if you simply overwrite a directory with a newer version of the app. DMD is not alone with this. You should always delete the directory first. It's precisely why the compiler does so. So, that proves nothing. You are simply ok with wasting the end users time... you should grow up and take responsibility for what you release. Your logic is not sound mathematically unless you think it's ok to waste end users time: There is 1 programmer, you and N end users of your app. Ok? got that? Very simple mathematics. Now, suppose you decide it is not worth your 10 mins to fix a problem or add sanity checks or robustness to your program and it effects 1% of the users of your app(we'll use a low percentage just to give you a fighting chance, which you don't deserve but we'll allow it). Now, suppose that wastes only 10 mins of the end users time(again, we'll low ball the number because usually it is much greater since the end user is not familiar with out the program works like the creator of that program is). This means that 10*0.01*N minutes are wasted overall of the human race because you didn't want to spend 10 minutes to fix a program. If 1 users use your app, that is 1000 minutes wasted ~= 17 hours. And that is a low estimate. So, just because you want to save 10 minutes you've wasted 17 hours of human life... what an investment! That is your mentality. You should run for US President! Your mentality fits right in with how the US handles it's money. Remember how much of your own life has been wasted on fixing other peoples mess and maybe you might realize how bad it is... probably not though, maybe when your on your death bed you might get a spark of sanity... but then it will be too late and pointless.
Re: It makes me sick!
On Friday, 28 July 2017 at 13:55:33 UTC, Anonymouse wrote: On Friday, 28 July 2017 at 05:14:16 UTC, FoxyBrown wrote: If dmd breaks in strange and unpredictable ways IT IS DMD's fault! No exceptions, no matter what you believe, what you say, what lawyer you pay to create a law for you to make you think you are legally correct! You can make any claim you want like: "The end user should install in to a clean dir so that DMD doesn't get confused and load a module that doesn't actually have any implementation" but that's just your opinion. At the end of the day it only makes you and dmd look bad when it doesn't work because of some lame minor issue that could be easily fixed. But it's not being installed, it's being manually extracted, meaning you can't even have cleanup scripts. Compare keeping an installation of audio files in mp3 (bird calls), and then getting an upgrade where they are in ogg in a new neat directory hierarchy. There's an installer that properly and cleanly removes the old mp3s before extracting the new files, as well as a bonus archive if you want to unzip it yourself. Manually extracting it onto the old directory puts the oggs next to the mp3s, leaving it with twice the number of original audio files. Meanwhile, the official upgrade path (installer) properly removes the stale ones. You can't reasonably expect your audio player to not list them all there. So, the program, if it is updated shouldn't use the mp3's then. Why the hell is the program that you say was upgraded to use the ogg still searching and using mp3's? You are trying to make up reasons why it shouldn't work... at least come up with valid reasons. Yes, there might be "twice" the files and one might waste space BUT that is different from the application crapping out and the end user spending hours trying to figure out what is wrong. TOTALLY different issues. We are not talking about "listing" files or anything like that, we are talking about the app not working because of "stale" files because it decided to use them, even though it should have been told not too because the whole point of the upgrade was to migrate from one set of files to another... and yet some idiot who programmed the app still had the app use the old files... it's the idiots fault... not the end user. What if the end user does a partial restore from some system issues and those mp4's were restored? Then what? The end users fault when he opens up the app and it crashes? Some programmers need to start taking responsibility for the crap they spew out. What a programmer is creating is effecting many many end users. It is up to the programmer to do the correct job to prevent a large factor of end user waste. That is what the programmer gets paid for.
Re: It makes me sick!
On Friday, 28 July 2017 at 01:10:03 UTC, Mike Parker wrote: On Friday, 28 July 2017 at 00:28:52 UTC, FoxyBrown wrote: You are not being very logical. The zip file as N files in it. No matter what those files are, it should be a closed system. That is, if I insert or add(not replace) M file to the directory structure it should not break D, period! That's *not* what happened here. Jonathan explained it quite well. std.datetime was refactored into a package, its contents split into new modules. When you import a module foo, dmd looks for: 1. foo.di 2. foo.d 3. foo/package.d When it finds one, it stops looking. It's not an error for all three to exist. Your error came because it found std/datetime.d, but you linked to a library that included symbols for std/datatetime/package.d. It's not the compiler's responsibility to error in that case. It's your responsibility to properly install. Sorry, wrong. Why? Because NO file in the zip should be referencing any file not in the zip unless it is designed to behave that way(e.g., an external lib or whatever). If an old external program is referencing a file in dmd2 that isn't in the new zip it should err. Why? Because suppose you have an old program that references some old file in dmd2 dir and you upgrade dmd2 by extracting the zip. The program MAY still work and use broke functionality that will go undetected but be harmful. Why? Because dmd.exe is reference a file it shouldn't and it should know it shouldn't yet it does so anyways. It really has nothing to do with the file being in the dir but that dmd is being stupid because no one bothered to sanity checks because they are too lazy/think it's irrelevant because it doesn't effect them. That's unreasonable. Nope, your unreasonable expecting the end user to clean up the mess "you" leave. I should be able to put any extra files anywhere in the dmd2 dir structure and it should NOT break dmd. There are numerous applications out there that can break if you simply overwrite a directory with a newer version of the app. DMD is not alone with this. You should always delete the directory first. It's precisely why the compiler does so. Nope. Virtually all apps, at least on windows, work fine if you replace their contents with new versions. Generally, only generated files such as settings and such could break the apps... but this is not the problem here. If dmd breaks in strange and unpredictable ways IT IS DMD's fault! No exceptions, no matter what you believe, what you say, what lawyer you pay to create a law for you to make you think you are legally correct! You can make any claim you want like: "The end user should install in to a clean dir so that DMD doesn't get confused and load a module that doesn't actually have any implementation" but that's just your opinion. At the end of the day it only makes you and dmd look bad when it doesn't work because of some lame minor issue that could be easily fixed. It suggests laziness["Oh, there's a fix but I'm too lazy to add it"], arrogance["Oh, it's the end users fault, let them deal with it"], and a bit of ignorance. In the long run, mentalities like yours are hurting D rather than helping it. Sure, you might contribute significantly to D's infrastructure, but if no one uses because there are so many "insignificant" issues then you've just wasted an significant portion of your life for absolutely nothing. So, I'd suggest you rethink your position and the nearsighted rhetoric that you use. You can keep the mentality of kicking the can down the road and blaming the end user but it will ultimately get you no where.
Re: It makes me sick!
On Thursday, 27 July 2017 at 23:37:41 UTC, Jonathan M Davis wrote: On Thursday, July 27, 2017 11:55:21 Ali Çehreli via Digitalmars-d-learn wrote: On 07/27/2017 11:47 AM, Adam D. Ruppe wrote: > On Thursday, 27 July 2017 at 18:35:02 UTC, FoxyBrown wrote: >> But the issue was about missing symbols, not anything >> "extra". If datatime.d is there but nothing is using it, >> why should it matter? > > YOU were using it with an `import std.datetime;` line. With > the file still there, it sees it referenced from your code > and loads the file... but since it is no longer used > upstream, the .lib doesn't contain it and thus missing > symbol. So, the actual problem is that given both datetime/package.d and datetime.d, the import statement prefers the file. It could produce a compilation error. If we don't want that extra check by the compiler, it would be better to keep datetime.d with a warning in it about the change. The warning could say "please remove this file". :) I think that this should obviously be a compilation error as should any case where you've basically declared the same module twice. And really, I don't see any reason to support extracting the new zip on the old folder. We've never said that that would work, and if you think it through, it really isn't all that reasonable to expect that it would work. The list of files changes from release to release (even if removals are rare), and the layout of the directories could change. So long as the sc.ini or dmd.conf does ther right thing, then that really isn't a problem. Obviously, it's more of a pain if folks are making manual changes, but we've never promised that the directory structure of each release would be identical or that copying one compiler release on top of another would work. - Jonathan M Davis You are not being very logical. The zip file as N files in it. No matter what those files are, it should be a closed system. That is, if I insert or add(not replace) M file to the directory structure it should not break D, period! Why? Because NO file in the zip should be referencing any file not in the zip unless it is designed to behave that way(e.g., an external lib or whatever). If an old external program is referencing a file in dmd2 that isn't in the new zip it should err. Why? Because suppose you have an old program that references some old file in dmd2 dir and you upgrade dmd2 by extracting the zip. The program MAY still work and use broke functionality that will go undetected but be harmful. Why? Because dmd.exe is reference a file it shouldn't and it should know it shouldn't yet it does so anyways. It really has nothing to do with the file being in the dir but that dmd is being stupid because no one bothered to sanity checks because they are too lazy/think it's irrelevant because it doesn't effect them. I should be able to put any extra files anywhere in the dmd2 dir structure and it should NOT break dmd. It's like if I put a text file in some OS directory and the OS decides to use that file and crash the OS and not boot... it could happen, but it shouldn't. In fact, all of phobos should be versioned. Each module should have a version id embedded in it. Each release all the versions are updated before shipping.
Re: It makes me sick!
On Thursday, 27 July 2017 at 18:14:52 UTC, Steven Schveighoffer wrote: On 7/27/17 1:58 PM, FoxyBrown wrote: On Thursday, 27 July 2017 at 12:23:52 UTC, Jonathan M Davis wrote: On Wednesday, July 26, 2017 22:29:00 Ali Çehreli via Digitalmars-d-learn wrote: On 07/26/2017 09:20 PM, FoxyBrown wrote: >> Somebody else had the same problem which they solved by removing >> >> "entire dmd": >> http://forum.dlang.org/thread/ejybuwermnentslcy...@forum.dlang.org >> >> Ali > > Thanks, that was it. So I guess I have to delete the original dmd2 dir > before I install each time... didn't use to have to do that. Normally, it shouldn't be necessary. The splitting of the datetime package[1] had this effect but I'm not sure why the installation process can't take care of it. Ali [1] http://dlang.org/changelog/2.075.0.html#split-std-datetime It _should_ take care of it. The fact that multiple people have run into this problem and that the solution was to remove dmd and then reinstall it implies that there's a bug in the installer. - Jonathan M Davis I do not use the installer, I use the zip file. I assumed that everything would be overwritten and any old stuff would simply go unused.. but it seems it doesn't. If the other person used the installer then it is a problem with dmd itself not designed properly and using files that it shouldn't. I simply unzip the zip file in to the dmd2 dir and replace sc.ini... that has been my MO for since I've been trying out dmd2 and only recently has it had a problem. If you extracted the zip file over the original install, then it didn't get rid of std/datetime.d (as extracting a zipfile doesn't remove items that exist on the current filesystem but aren't in the zipfile). So I can totally see this happening. I don't know of a good way to solve this except to tell people, don't do that. -Steve But the issue was about missing symbols, not anything "extra". If datatime.d is there but nothing is using it, why should it matter? Why would it have any effect on the compilation process and create errors with D telling me something is being used that isn't? dmd shouldn't be picking up extraneous and non-connected files just for the fun of it. Basically, if no "references" escape out side of the D ecosystem, then there shouldn't be a problem.
Re: It makes me sick!
On Thursday, 27 July 2017 at 12:23:52 UTC, Jonathan M Davis wrote: On Wednesday, July 26, 2017 22:29:00 Ali Çehreli via Digitalmars-d-learn wrote: On 07/26/2017 09:20 PM, FoxyBrown wrote: >> Somebody else had the same problem which they solved by removing >> >> "entire dmd": >> http://forum.dlang.org/thread/ejybuwermnentslcy...@forum.dlang.org >> >> Ali > > Thanks, that was it. So I guess I have to delete the original dmd2 dir > before I install each time... didn't use to have to do that. Normally, it shouldn't be necessary. The splitting of the datetime package[1] had this effect but I'm not sure why the installation process can't take care of it. Ali [1] http://dlang.org/changelog/2.075.0.html#split-std-datetime It _should_ take care of it. The fact that multiple people have run into this problem and that the solution was to remove dmd and then reinstall it implies that there's a bug in the installer. - Jonathan M Davis I do not use the installer, I use the zip file. I assumed that everything would be overwritten and any old stuff would simply go unused.. but it seems it doesn't. If the other person used the installer then it is a problem with dmd itself not designed properly and using files that it shouldn't. I simply unzip the zip file in to the dmd2 dir and replace sc.ini... that has been my MO for since I've been trying out dmd2 and only recently has it had a problem.
Re: It makes me sick!
On Thursday, 27 July 2017 at 03:41:06 UTC, Ali Çehreli wrote: On 07/26/2017 08:34 PM, FoxyBrown wrote: Knowing that every time I upgrade to the latest "official" D compiler I run in to trouble: Win32\Debug DMD\test.obj(test) Error 42: Symbol Undefined _D3std8datetime7SysTime8toStringMxFNbNfZAya (const(nothrow @safe immutable(char)[] function()) std.datetime.SysTime.toString) Win32\Debug DMD\test.obj(test) Somebody else had the same problem which they solved by removing "entire dmd": http://forum.dlang.org/thread/ejybuwermnentslcy...@forum.dlang.org Ali Thanks, that was it. So I guess I have to delete the original dmd2 dir before I install each time... didn't use to have to do that.
Re: It makes me sick!
And yes, I'm using the correct phobos(the one that came with dmd2).
It makes me sick!
Knowing that every time I upgrade to the latest "official" D compiler I run in to trouble: Win32\Debug DMD\test.obj(test) Error 42: Symbol Undefined _D3std8datetime7SysTime8toStringMxFNbNfZAya (const(nothrow @safe immutable(char)[] function()) std.datetime.SysTime.toString) Win32\Debug DMD\test.obj(test) Error 42: Symbol Undefined _D3std8datetime7SysTime6toHashMxFNaNbNiNfZk (const(pure nothrow @nogc @safe uint function()) std.datetime.SysTime.toHash) Win32\Debug DMD\test.obj(test) Error 42: Symbol Undefined _D3std8datetime7SysTime8opEqualsMxFNaNbNfKxS3std8datetime7SysTimeZb (const(pure nothrow @safe bool function(ref const(std.datetime.SysTime))) std.datetime.SysTime.opEquals) Win32\Debug DMD\test.obj(test) Error 42: Symbol Undefined _D3std8datetime7SysTime8__xopCmpFKxS3std8datetime7SysTimeKxS3std8datetime7SysTimeZi (int std.datetime.SysTime.__xopCmp(ref const(std.datetime.SysTime), ref const(std.datetime.SysTime))) Win32\Debug DMD\test.obj(test) Error 42: Symbol Undefined _D3gtk3All12__ModuleInfoZ (gtk.All.__ModuleInfo) \GtkD\x86\gtkd.lib(AboutDialog) Error 42: Symbol Undefined _D3std6format64__T14formatIntegralTS3std5array17__T8AppenderTAyaZ8AppenderTmTaZ14formatIntegralFNaNbNfS3std5array17__T8AppenderTAyaZ8AppenderxmKxS3std6format18__T10FormatSpecTaZ10FormatSpeckmZv (pure nothrow @safe void std.format.formatIntegral!(std.array.Appender!(immutable(char)[]).Appender, ulong, char).formatIntegral(std.array.Appender!(immutable(char)[]).Appender, const(ulong), ref const(std.format.FormatSpec!(char).FormatSpec), uint, ulong)) \GtkD\x86\gtkd.lib(AboutDialog) Error 42: Symbol Undefined _D3std5stdio6stderrS3std5stdio4File (std.stdio.File std.stdio.stderr) \GtkD\x86\gtkd.lib(Implement) Error 42: Symbol Undefined _D3std6format64__T14formatUnsignedTS3std5array17__T8AppenderTAyaZ8AppenderTmTaZ14formatUnsignedFNaNbNfS3std5array17__T8AppenderTAyaZ8AppendermKxS3std6format18__T10FormatSpecTaZ10FormatSpeckbZv (pure nothrow @safe void std.format.formatUnsigned!(std.array.Appender!(immutable(char)[]).Appender, ulong, char).formatUnsigned(std.array.Appender!(immutable(char)[]).Appender, ulong, ref const(std.format.FormatSpec!(char).FormatSpec), uint, bool)) Error: linker exited with status 8 Building Win32\Debug DMD\test.exe failed! I recompiled gtkD with the new compiler, same result. My code was working before the upgrade just fine and I did not change anything.
Re: Silent error when using hashmap
On Thursday, 27 July 2017 at 02:30:17 UTC, FatalCatharsis wrote: On Thursday, 27 July 2017 at 01:21:40 UTC, Steven Schveighoffer wrote: [...] This appears to be it. When an error is thrown, stdout does not flush. When I put stdout.flush() immediately after the writeln("start") at the beginning it is printed correctly. However, when I try to catch the error and then do stdout.flush() in main, it does not print. Do you know of a way to make D always flush the output buffer when an error is thrown? On Thursday, 27 July 2017 at 01:05:28 UTC, ketmar wrote: [...] Yes, I understand this. This is not my question. My question is why all previous output to the console does not occur before the error is thrown. As Steve said, this is because the output buffer is not flushed when an error occurs. I just noticed this without an exception. I changed my writeln's to write and printed a "\n" but it did not flush. Had to flush it manually. Not sure if that is by design or what.
GtkD on android?
With LDC's new ability to do android/arm, we are missing the ability to do GUI's? Can any of the current D solutions work such as GtkD or QtD? I'm looking for something somewhat lightweight, easy to use(I find GtkD a bit funky but it does seem to work and is relatively easy once one gets through the basics). I think having a GUI builder is crucial though as it makes it so much easier in the long run. Glade is a bit funky but functional and works. Ideally I'd like to be able to make portable apps that just work across the board(mac, linux, windows, android) without much hassle.
Re: find difference between two struct instances.
On Saturday, 22 July 2017 at 01:04:48 UTC, Nicholas Wilson wrote: On Friday, 21 July 2017 at 23:38:51 UTC, FoxyBrown wrote: [...] use opCmp in conjunction with __traits(allMembers,T) struct Example { int a,b,c; string d,e,f; } void difference(alias func, T)(T t1, T t2) if(__traits(compiles, func(t1,t2))) { foreach(U; __traits(allMembers,T) { if (mixin("t1." ~ U.stringof~ ".opCmp(t2." ~ U.stringof ~")") func(t1,t2); } } auto a = Example(1,2,3,"foo","bar",baz"); auto a = Example(1,2,42,"foo","bar",quux"); difference!(writeln)(a,b); // hopefully prints 343\nbazquux Not tested but should give you an idea to adapt as needed. thanks, I'll try it out.
Re: executeShell not working
On Saturday, 22 July 2017 at 02:31:45 UTC, FoxyBrown wrote: auto sss = "sc config \""~szSvcName~"\" start= disabled"; executeShell("sc config \""~szSvcName~"\" start= disabled"); but if I copy and paste the string in to an admin console, it works fine: sc config "W32Time" start= disabled [SC] ChangeServiceConfig SUCCESS szSvcName is W32Time. It's not an admin issue. I *can't* set it to other states either. Does executeShell not run it's process with the same rights as the app? even spawnProcess isn't doing it spawnProcess(["C:\\Windows\\System32\\sc.exe","config", szSvcName, "start=","disabled"]); or spawnProcess(["C:\\Windows\\System32\\sc.exe","config "~szSvcName~" start= disabled"]);
executeShell not working
auto sss = "sc config \""~szSvcName~"\" start= disabled"; executeShell("sc config \""~szSvcName~"\" start= disabled"); but if I copy and paste the string in to an admin console, it works fine: sc config "W32Time" start= disabled [SC] ChangeServiceConfig SUCCESS szSvcName is W32Time. It's not an admin issue. I *can't* set it to other states either. Does executeShell not run it's process with the same rights as the app?
Re: find difference between two struct instances.
On Friday, 21 July 2017 at 22:35:20 UTC, Era Scarecrow wrote: On Friday, 21 July 2017 at 21:03:22 UTC, FoxyBrown wrote: Is there a way to easily find the differences between to struct instances? I would like to report only the differences e.g., writeln(s1 - s2); prints only what is different between s1 and s2. No, it isn't. It is a concept, wasn't mean to be taken as literal D code. This is entirely dependent on the structs in question, you can't just subtract any struct from another struct unless it knows how to do it. Depends on what the structures hold. You'll probably have to either make an opSub, a function to call opBinary!"-", or do opCmp which returns which is higher/lower (and may be as simple as subtraction). Why do I want to go through all that trouble? A simple binary compare should suffice.
find difference between two struct instances.
Is there a way to easily find the differences between to struct instances? I would like to report only the differences e.g., writeln(s1 - s2); prints only what is different between s1 and s2.
How to get value of type at CT given only an alias
Trying to do some tricky stuff but I can't seem to get the value of a type(enum in my case, but must work in general). Basically, given a type T or an alias T(alias preferred), I'd like to be able to get the "default value" of that type. e.g., if it is an enum and I have an alias to a member, instead of (Enum)3 I want 3. if it is a member field, I want the default value. if it is a function pointer, the address(probably 0, but whatever). Basically a sort of generic "getValue" that attempts to get the CT value of any type, if it exists. (obviously the value of class is meaningless, so returns ""... class isn't even a type, but can still query). In fact, I'd like to also naturally resolve the value back in to the expression that created it. e.g., (Enum)3 -> Enum.ThirdEntry
nogc string concatenation?
Anyone have an efficient implementation that is easy to use?
Re: WTF is going on! Corrupt value that is never assigned
On Thursday, 13 July 2017 at 23:30:39 UTC, Moritz Maxeiner wrote: On Thursday, 13 July 2017 at 22:53:45 UTC, FoxyBrown wrote: On Thursday, 13 July 2017 at 20:35:19 UTC, Moritz Maxeiner wrote: On Thursday, 13 July 2017 at 18:22:34 UTC, FoxyBrown wrote: The following code is pretty screwed up, even though it doesn't look like it. I have a buf, a simple malloc which hold the results of a win32 call. I am then trying to copy over the data in buf to a D struct. But when copying the strings, the buf location changes, screwing up the copying process. It shouldn't happen, buf never changes value anywhere except the first malloc(which is once). Somehow it is getting changed, but where? [...] The buf value changes when calling cstr2dstr but I've had it with other values to(any function call such as to!string, etc seems to trigger it). [...] - Does this happen every time, or only sometimes? yes, but I've been having this problem and not sure if it was quite as consistent as before or that I just recognized it. - At which loop iteration does it occur? Now it seems to occur after the first iteration, but I've add it happen after a while and in other cases it's worked.. depends on if I use malloc, or a D array, or what. - Which compiler (+version) are you using (with what flags)? Latest DMD official.. whatever default flags exist in debug mode with visual D... why should it matter? [...] Because it's part of the usual "Steps to reproduce" you are supposed to provide so others can verify what you're encountering. - What are the steps to reproduce (i.e. does this e.g. happen with a main that consist of one call to EnumServices) ? Yes, It is basically the first thing I do when I run my program. [...] Okay, I'll setup a Windows VM when I have time and check it out (unless someone solves it beforehand). because D is not interfacing well with C. First, the win32 function does not simply fill in an array but adds additional junk at the end(didn't know that until after a few wasted hours trying to get it to fill in an array properly). To be fair, that's neither C nor D fault; that's Microsoft providing unintuitive, horrible APIs and doing an amazing job of providing documentation (MSDN) that *appears* to be exhaustive and well written, but misses all these little important details that you actually have to know in order to program correct control logic, driving you to the edge of sanity. Been there, done that. I have generally not had that problem. Usually works as it does and pretty straight forward. Might have to fish a little for info from others but most things have been worked out by someone somewhere. What I'm trying to do is fairly straightforward but I've wasted nearly 2 days on it. I had no issues starting or stopping services but I can't get the enumerate code to work(the winapi function works fine, it's getting the info out of what it passes in to D that is the problem). There is no explanation why buf is being changed, I never change it after it is initialized, yet, it changes somehow. Either it is being overwritten because of a pointer that is invalid or it is a stack problem. It is most likely the former, but I have tried many different ways and they all lead to similar results.
Why is dlang.org having so many problems lately? I constantly have issues connecting.
? Pretty much at least several times a day I cannot connect. Either stalls, forum is down, etc.
Re: WTF is going on! Corrupt value that is never assigned
On Thursday, 13 July 2017 at 20:35:19 UTC, Moritz Maxeiner wrote: On Thursday, 13 July 2017 at 18:22:34 UTC, FoxyBrown wrote: The following code is pretty screwed up, even though it doesn't look like it. I have a buf, a simple malloc which hold the results of a win32 call. I am then trying to copy over the data in buf to a D struct. But when copying the strings, the buf location changes, screwing up the copying process. It shouldn't happen, buf never changes value anywhere except the first malloc(which is once). Somehow it is getting changed, but where? [...] The buf value changes when calling cstr2dstr but I've had it with other values to(any function call such as to!string, etc seems to trigger it). [...] - Does this happen every time, or only sometimes? yes, but I've been having this problem and not sure if it was quite as consistent as before or that I just recognized it. - At which loop iteration does it occur? Now it seems to occur after the first iteration, but I've add it happen after a while and in other cases it's worked.. depends on if I use malloc, or a D array, or what. - Which compiler (+version) are you using (with what flags)? Latest DMD official.. whatever default flags exist in debug mode with visual D... why should it matter? buf is changing on the only source of that change could be through the winapi call or the temp pointer used to index it.. which is never assigned to, so it can't be modifying it. The c2d function, when called, clearly has no understanding of buff, yet after it returns, it is causing the problem. This seems like the stack is being corrupted by the function call. - What are the steps to reproduce (i.e. does this e.g. happen with a main that consist of one call to EnumServices) ? Yes, It is basically the first thing I do when I run my program. It is a rather isolated function(Just trying to get a list of current services, which has been a total PITA because D is not interfacing well with C. First, the win32 function does not simply fill in an array but adds additional junk at the end(didn't know that until after a few wasted hours trying to get it to fill in an array properly). Hence now I'm trying to convert the returned data one iteration at a time rather than all at once, but I can't get that to work because the pointer to the buffer I created is changing. I could use a temp and get it to work, but that doesn't explain what the hell is going on. The value of buff seems to be erratic, I've had it point valid stuff(other data) and then have small values in it like 8. I don't know how any stack corruption could be occurring but that is exactly what it looks like. "Return from function call and "static variables"(with respect to the call) are changed.". But that seems really hard to sell given that it's pretty simple and D should have all those basics well covered.
WTF is going on! Corrupt value that is never assigned
The following code is pretty screwed up, even though it doesn't look like it. I have a buf, a simple malloc which hold the results of a win32 call. I am then trying to copy over the data in buf to a D struct. But when copying the strings, the buf location changes, screwing up the copying process. It shouldn't happen, buf never changes value anywhere except the first malloc(which is once). Somehow it is getting changed, but where? The specific win32 or style is irrelevant, I am talking either about a bug or some subtle D thing because the code makes sense. (Fill Buf, iterate through buffer copying over to D values). I've ran in to this before, D does something fishy and it wastes hours upon hours trying to track done some stupid little thing it does. The buf value changes when calling cstr2dstr but I've had it with other values to(any function call such as to!string, etc seems to trigger it). struct ServiceData { wstring Name; wstring LongName; int Type; int State; int ControlsAccepted; int Win32ExitCode; int SpecificExitCode; int CheckPoint; int WaitHint; int ProcessId; int Flags; } auto cstr2dstr(wchar* cstr) { import std.array; auto str = appender!wstring; auto len = lstrlen(cstr); str.reserve(len); for(int i = 0; i < len; i++) str.put(cstr[i]); return str.data; } auto EnumServices() { import core.stdc.stdlib, std.traits; ServiceData[] servicesList; auto buf = malloc(5); // Gets changed later, even though never an assignment auto buf2 = buf; // does not change auto schSCManager = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); if (NULL == schSCManager) { print("OpenSCManager failed (%d)\n", GetLastError()); return servicesList; } DWORD dwBytesNeeded, dwCount, lpResumeHandle, resume, totalCount; auto servicesType = (SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32 | SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS); int cnt = 0; auto res = 0; do { // Manually copy over data, this is because EnumSErvicesStatus adds data at end of array for some odd ball reason making it difficult to build the correct array sequentially for(int i = 0; i < dwCount; i++) { ENUM_SERVICE_STATUS_PROCESSW x; ServiceData d; auto s = cast(ENUM_SERVICE_STATUS_PROCESSW*)(buf + i*ENUM_SERVICE_STATUS_PROCESSW.sizeof); //before buf is of correct value d.Name = cstr2dstr(s.lpServiceName); //after buf is invalid, yet buf is never assigned } res = EnumServicesStatusExW(schSCManager, SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, SERVICE_STATE_ALL, cast(ubyte*)buf, 5, , , , cast(const(char)*)null); if (ERROR_MORE_DATA != GetLastError()) { print("Error enumerating services."); break; } } while (res == 0); for(int i = 0; i < totalCount; i++) { auto s = servicesList[i]; writeln(s.Name, " - ", s.LongName, " - ", s.Type, " = ", s.State); } return servicesList; }
Whats the correct way to pass a D array type to a win32 api function wanting a buffer?
Everything I do results in some problem, I've tried malloc but then converting the strings resulted in my program becoming corrupted. Heres the code: auto EnumServices() { auto schSCManager = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); if (NULL == schSCManager) { print("OpenSCManager failed (%d)\n", GetLastError()); return null; // Why can't we return a null? Surely we don't have to cast a null in to a typeof null? } import core.stdc.stdlib; DWORD dwBytesNeeded, dwCount, lpResumeHandle, resume; auto servicesType = (SERVICE_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_KERNEL_DRIVER | SERVICE_WIN32 | SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS); ENUM_SERVICE_STATUS_PROCESS[5000] services; auto res = SVC.EnumServicesStatusExA(schSCManager, SC_ENUM_TYPE.SC_ENUM_PROCESS_INFO, servicesType, SERVICE_STATE_ALL, cast(ubyte*)services.ptr, 5000*ENUM_SERVICE_STATUS_PROCESS.sizeof, , , , cast(const(char)*)null); for(int i = 0; i < dwCount; i++) { auto s = services[i].lpServiceName; writeln(*s); } return services; }
.NET Library In D
I was able to get my C# to D convert to convert about 25% of the .net library v4.6 It converts the following libs: // System.CodeDom // System.CodeDom.Compiler // System.Collections.Concurrent // System.Collections.Generic // System.Collections.ObjectModel // System.Collections.Specialized // System.ComponentModel // System.ComponentModel.Design // System.ComponentModel.Design.Serialization // System.Configuration // System.Configuration.Internal // System.Diagnostics // System.Diagnostics.CodeAnalysis // System.IO // System.IO.Compression // System.IO.Ports // System.Media // System.Timers // System.Text.RegularExpressions Not all code works depending on the specific but 90%+ does. The goal is that, one day, we can effectively replace the phobos with .NET semantics if we want. It, being a nicer library, and all the source code available through reflection, makes it a nice target. While the source code cannot be distributed, the recompiler can. In C# maps to D farily well, it is not a difficult ask.
.NET Library In D
I was able to get my C# to D convert to convert about 25% of the .net library v4.6 It converts the following libs: // System.CodeDom // System.CodeDom.Compiler // System.Collections.Concurrent // System.Collections.Generic // System.Collections.ObjectModel // System.Collections.Specialized // System.ComponentModel // System.ComponentModel.Design // System.ComponentModel.Design.Serialization // System.Configuration // System.Configuration.Internal // System.Diagnostics // System.Diagnostics.CodeAnalysis // System.IO // System.IO.Compression // System.IO.Ports // System.Media // System.Timers // System.Text.RegularExpressions Not all code works depending on the specific but 90%+ does. The goal is that, one day, we can effectively replace the phobos with .NET semantics if we want. It, being a nicer library, and all the source code available through reflection, makes it a nice target. While the source code cannot be distributed, the recompiler can. In C# maps to D farily well, it is not a difficult ask.
Re: Why no offsetof for static struct?
On Monday, 10 July 2017 at 20:13:46 UTC, Adam D. Ruppe wrote: On Monday, 10 July 2017 at 20:01:39 UTC, FoxyBrown wrote: Cannot get the offset of static members of a struct That's because static members do not have an offset. They are not part of the struct in memory, just in name. We can clearly get a pointer to the static struct X There's barely any such thing as a static struct. That's just a struct that stands without outside context which is almost all structs, actually, so the term isn't special. since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). No, it isn't. Static members are stored in an entirely different place than non-static members. They are really just global variables in memory with their in-source name being nested somewhere else. This is not true, just because there isn't any official statement, or even if denied, does not make it true. I have proof: auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Returns the address of a struct's static members. It's pretty obvious, the compiler seems to instantiate the static members simply as a sort of "singleton". They are laid out with the same relative offsets as the struct(which is obvious, as that is the most natural way). That is all that is needed to treat the memory the static variables use as the struct in which they are part of. No need to make it any more complex than that. Just because D obfuscates that static structs have addresses, doesn't mean they don't. No need to perpetuate a misnomer. Static structs and classes have addresses. No, it might not be officially supported and the compiler may end up doing something funky, but it works, and works as it should, and should become part of D because it is useful: auto GetOpts(T)(string[] args) { import std.getopt, std.meta, std.traits; auto t = GetStaticAddress!(T)(); string combine() { string s = ""; foreach(m; AliasSeq!(__traits(allMembers, T))) { mixin("enum a = __traits(getAttributes, T."~m~")[0];"); mixin("s ~= \"`"~a~"`, &"~T.stringof~"."~m~", \";"); } return s; } enum s = combine(); mixin("return getopt(args, "~s~");"); } struct X { align(1): __gshared public static: @("A") bool A; @("B") string B; @("C") string[] C; }; which allows us to do GetOps!X(args) vs getop(args, "A", , "B", , "C", ); replaces the overly verbose getopt. Tell me that isn't useful and tell me that static structs don't have addresses!
Why no offsetof for static struct?
Cannot get the offset of static members of a struct struct X { __gshared public: int x; } X.x.offsetof < invalid. We can clearly get a pointer to the static struct X since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). e.g., auto p = cast(X*) will, for all practical purposes be a pointer to X. auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Of course, assuming that the first member is at the same location as the start of the struct and the elements are laid out in the same positions(not sure if this is guaranteed, but probably is). Would be much nicer if we could just take the address of a static struct This is pretty useful for simplification: auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } auto GetOpts(T)(string[] args) { import std.getopt, std.meta, std.traits; auto t = GetStaticAddress!(T)(); string combine() { string s = ""; foreach(m; AliasSeq!(__traits(allMembers, T))) { mixin("enum a = __traits(getAttributes, T."~m~")[0];"); mixin("s ~= \"`"~a~"`, &"~T.stringof~"."~m~", \";"); } return s; } enum s = combine(); mixin("return getopt(args, "~s~");"); } struct X { align(1): __gshared public static: @("A") bool A; @("B") string B; @("C") string[] C; }; which allows us to do GetOps!X(args) vs getop(args, "A", , "B", , "C", ); Could be improved to only deal with special argument attributes on X's fields and allow for non-static strucs(for the general case of mapping). Sort of a map between attribute space on a type and some function.
Why no offsetof for static struct?
Cannot get the offset of static members of a struct struct X { __gshared public: int x; } X.x.offsetof < invalid. We can clearly get a pointer to the static struct X since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). e.g., auto p = cast(X*) will, for all practical purposes be a pointer to X. auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Of course, assuming that the first member is at the same location as the start of the struct and the elements are laid out in the same positions(not sure if this is guaranteed, but probably is). Would be much nicer if we could just take the address of a static struct
How to get the address of a static struct?
static struct S { public static: int x; string a; } auto s = // ?!?!?! invalid because S is a struct, but... basically s = S. So S.x = s.x and s.a = S.a; Why do I have to do this? Because in visual D, global structs don't show up in the debugger. So if I create a local alias, I can see see them, but I don't wanna have to do one variable for each variable in the struct...
iterate over variadic
How can we iterate over a variadic and have it's index. I'll do different things depend on if it's an even or odd index, but seems to be no way to get it.
Variadic Template Pattern
Hi, I have a proposal, wondering about your opinions. Suppose one has a template function foo that accepts a variable number of parameters: auto foo(T...)(); Suppose we actually want to have some type of order and type info instead: auto foo(int, string)(); but we need a "variable" number of them such as auto foo(int, string, int, string)(); auto foo(int, string, int, string, int, string)(); ad nausea. We could simplify it all by allowing for a sort of pattern on the ... for variadics: auto food((int,string)...)(); and, this, of course, expands to what was described earlier. Now, this can be accomplished already with the single template method and foreach/static if testing the type, but that seems like it's excessively verbose.
Why is phobos so wack?
import string. ... return str.join(" "); gives Error: template std.array.join cannot deduce function from argument types !()(string, string), candidates are: \..\..\src\phobos\std\array.d(1591):std.array.join(RoR, R)(RoR ror, scope R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))) \..\..\src\phobos\std\array.d(1668):std.array.join(RoR, E)(RoR ror, scope E sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && is(E : ElementType!(ElementType!RoR))) \..\..\src\phobos\std\array.d(1754): std.array.join(RoR)(RoR ror) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR))) simply trying to join a string[] with a separator. I tend to get these types of errors when doing simple things in D. Virtually every other programming language just works as expected. You can pretty much just jump in there and pretty much guess at the function name, the arguments, and it will work. In Phobos, seems like it follows an anti-pattern. You always end up having to look at documentation unless you are familiar enough with D and use it in a regular basis to remember its quirks and odd behavior. Seems that the same functions are defined differently in different modules and the modules not always the expected ones. (strip is another one that throws me for a loop. I always try trim first... that is what everyone else uses, yeah, it's just a name, but then why strip?) Phobos seems to be rather unorganized and not logically put together. Any hopes of this ever getting fixed or do I need to start putting together my own library?
Re: All asserts need to have messages attached! Explicit as possible!
On Saturday, 8 July 2017 at 02:23:53 UTC, Jonathan M Davis wrote: On Saturday, July 8, 2017 12:55:46 AM MDT FoxyBrown via Digitalmars-d wrote: I came across some error in heap sort. Was erroring out on the wrong. A few lines below the assert existed but no error message associated, why is it so hard to not write a few extra EXTREMELY helpful error messages? assert(isHeap(r), "This is an ERROR AT THIS LOCATION"~__FILE__~"("~__LINE__~")"); etc? It should be mandatory that all asserts, throws, etc provide correct information about not only the point of the error but also the location and what caused it. These things are not irrelevant but affect all those that use it... imagine the real human man hours that could be saved if such things were done. It would be easy to find all the bad asserts? AssertError already provides the location of the assertion, and it uses __FILE__ and __LINE__ to do it (_all_ Exception types do that unless the person who wrote the class screwed up the constructor), so adding them to the message it pointless and redundant. If the assertion failure is printing out the wrong line, then it's likely either because you're looking at the wrong version of the code or because a string mixin is screwing with the line numbers (which IMHO, shouldn't happen, but it at least used to be a problem). In addition, the AssertError should be giving you a stack trace, which _should_ have the file and line numbers in it of every call in the stack (though stupidly, the line numbers don't always work, depending on your OS). So, you _should_ have had that information by the simple fact that an AssertError was thrown, and unless the assertion itself needed additional explanation beyond the condition that failed, then a message wouldn't have helped anyway. So, if the file and line number was wrong, the question is why, and that should be fixed. And we really need to figure out how to make it so that the issue of not having line numbers with stack traces goes away and stays away. The fact that it's been a problem is ridiculous, because file and line numvbers in stack traces are critical for debugging. - Jonathan M Davis But you miss the complete point, You focused on what D does rather than what it doesn't, which is what lead me to the problem in the first place. You are seeing the glass half full, rather than half empty, my friend. Shall I explain it so it makes sense? I was writing a natural sorting routine so I could get some string array sorted. This is because D is missing the capabilities to do a natural sort correctly. It does not compare the the integer in string a with the matching integer in string B correctly. If they happen to be a different length then it assumes the shorter one was smaller. At least, when I tried it, that is what I remember being the problem, or some other weird behavior, but it was not correct. Therefore, I decided to write the natural sorting routine to fix that(This is because I am a person that wants to drink a full glass of water rather than an empty glass). To implement the algorithm is rather simple in some ways and complicated in others. string[] naturalSort(string[] arr) /*pure @safe*/ { alias myComp = (x, y) { return ComplexPart(x,y); }; auto x = arr.sort!(myComp).release; return x; } bool ComplexPart(string x, string y) { auto ml = cast(int)(min(x.length, y.length)-1); auto ofsX = -1; auto ofsY = -1; auto numX_found = -1; auto numY_found = -1; for(int i = 0; i <= ml; i++) { // If one string is left slice of the other, it wins if (i >= ml || ofsX >= ml || ofsY >= ml) { if (x.length < y.length) return true; return false; } ofsX++; ofsY++; // If characters are not a digit, use default comparer if (!isDigit(x[ofsX]) || !isDigit(y[ofsY])) { if (x[ofsX] != y[ofsY]) return x[ofsX] < y[ofsY]; continue; } // We now know that x and y are identical up to the digit sequence. Extract these sequences then compare, if identical *in value*(000 = 0, etc) we continue the compare, else we compare the numbers and use that to specify the comparision quality while (ofsX < ml && isDigit(x[ofsX])) { ofsX++; }; while (ofsY < ml && isDigit(y[ofsY])) { ofsY++; }; auto numX = x[i..ofsX]; auto numY = y[i..ofsY]; auto res = compareStringNum(numX, numY);
All asserts need to have messages attached! Explicit as possible!
I came across some error in heap sort. Was erroring out on the wrong. A few lines below the assert existed but no error message associated, why is it so hard to not write a few extra EXTREMELY helpful error messages? assert(isHeap(r), "This is an ERROR AT THIS LOCATION"~__FILE__~"("~__LINE__~")"); etc? It should be mandatory that all asserts, throws, etc provide correct information about not only the point of the error but also the location and what caused it. These things are not irrelevant but affect all those that use it... imagine the real human man hours that could be saved if such things were done. It would be easy to find all the bad asserts?
Re: Application settings
On Friday, 7 July 2017 at 20:45:36 UTC, Moritz Maxeiner wrote: On Friday, 7 July 2017 at 19:40:35 UTC, FoxyBrown wrote: What's the "best" way to do this? I want something I can simply load at startup in a convenient and easy way then save when necessary(possibly be efficient at it, but probably doesn't matter). Simply json an array and save and load it, or is there a better way? "best" always depends on your specific use case. I use json files via asdf [1] [1] https://github.com/tamediadigital/asdf Seems like quite a heavy package for what I need. I just want to write a AA to disk and load it, ultimately.
Application settings
What's the "best" way to do this? I want something I can simply load at startup in a convenient and easy way then save when necessary(possibly be efficient at it, but probably doesn't matter). Simply json an array and save and load it, or is there a better way? Ideally, I'd like to store the settings as part of the binary to keep everything together but that poses a few issues I think.
Re: Vibe.d - very low performance
On Thursday, 6 July 2017 at 10:57:31 UTC, Sönke Ludwig wrote: Am 06.07.2017 um 09:27 schrieb Marek: https://www.techempower.com/benchmarks/#section=data-r14=ph=plaintext C++, Java and Go frameworks have very high performance. Vibe.d is supposed to have similar performance, but in fact vibe.d performance is very low. Why? This is a scalability issue, which should hopefully be fixed with 0.8.0. I'll open a PR once that is out. Basically with the version that was used in the last benchmark round, it didn't scale at all, and they use a server with many cores (40 + hyperthreading). So you are saying that will solve the nearly 200x factor from the top? At least get it in the top 20?
Re: Address of a lambda
On Friday, 7 July 2017 at 17:52:25 UTC, Ali Çehreli wrote: On 07/07/2017 10:33 AM, FoxyBrown wrote: > [...] the methods > [...] I'm not a user but I don't think it's right. According to the following, it takes a delegate: [...] Thanks, I guess one doesn't need to pass the address(I copied the code from somewhere and it was so I made an assumption). One doesn't need the delegate keyword or &, but the question then is why does & work? Seems to have done not affect the behavior.
Address of a lambda
In gtk, we routinly have to use delegates for callbacks. But the methods that accept these delegates want the address of the delegate, this prevents us from being able to pass a lambda in directly, but there really is not reason why we shouldn't be able to do this? Fine: void main() { bool windowDelete(Event event, Widget widget) { Main.quit(); return false; } MainWindow.addOnDelete(); } Invalid: void main() { MainWindow.addOnDelete(&((Event event, Widget widget) { Main.quit(); return false; })); } and yet, the only difference is a copy and paste(i.e., a rewrite rule, at most). Surely the compiler can figure out that we can take such an address because anything that actually exists must have an address somewhere. Seems like an arbitrary blocker? Even if it saves us from some obscure problems, it should work in most cases and be allowed when used in those cases. What's even stranger is that the function windowDelete must be declared in some type of object, such as another function, so it is actually a delegate, if one has it in the module root then it is a normal function and cannot be passed to addOnDelete, even though, again, there is very little difference. Invalid: bool windowDelete(Event event, Widget widget) { Main.quit(); return false; } void main() { MainWindow.addOnDelete(); } I do know the difference between a delegate and a function, and I suppose addOnDelete should be defined to take a function instead? But how can we create a "delegate function" similar to the nested delegate in the first case that works so that we can pass them as delegates? And aside, shouldn't all functions really be delegates? Having a closure of the outer scope still holds at the module root level(the scope is the module root). While it's an extra argument to pass, it could simplify live a bit. The corner cases could be handled by explicitly forcing it to be a function.
Re: Need simple sound
Heres a better version that automatically generates a class wrapping the portaudio.dll. Need portaudio.di(possibly renamed to portaudio.d and imported). Still same problem as original though. import portaudio; import std.conv, std.stdio; import core.stdc.stdio; alias BOOL = ubyte; alias DWORD = uint; auto BuildDLLClassFromCHeader(alias modulename, string name)() { import std.traits, std.algorithm, std.meta; auto s = "extern (C) class " ~name~"\n{\n\timport ___import = "~moduleName!modulename~";\n"; mixin("import "~moduleName!modulename~";"); foreach(m; AliasSeq!(__traits(allMembers, modulename))) { mixin("alias member = " ~ fullyQualifiedName!(modulename) ~ "." ~ m ~ ";"); static if (is(typeof(member) == function)) static if (functionLinkage!member != "C") continue; else s ~= "\tpublic static typeof(___import."~__traits(identifier, member)~")* "~__traits(identifier, member)~";\n"; } return s ~ "}"; } void DllImport(alias T)(string dllName) { import core.sys.windows.windows, std.conv, std.meta; auto dll = LoadLibrary(to!wstring(dllName~"\0").ptr); if (dll == null) assert(0, "Cannot load DLL `"~dllName~"'"); foreach(fname; __traits(derivedMembers, T)) { auto func = GetProcAddress(dll, fname); enum s = "auto p = cast(void**)&"~T.stringof~"."~fname~"; *p = cast(typeof(p))func;"; mixin(s); } } mixin(BuildDLLClassFromCHeader!(portaudio, "PortAudioDLL")()); struct Phase { float left=0, right=0; } bool test = false; extern(C) int sawtooth(const(void)* inputBuffer, void* outputBuffer, size_t framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { test = true; auto phase = cast(Phase*)userData; auto pout = cast(float*)outputBuffer; enum vol = 0.2f; foreach(i; 0 .. framesPerBuffer) { *pout++ = vol * phase.left; *pout++ = vol * phase.right; phase.left += 0.01f; if (phase.left >= 1.0f) phase.left -= 2.0f; phase.right += 0.03f; if (phase.right >= 1.0f) phase.right -= 2.0f; } return 0; } int main() { DllImport!PortAudioDLL("portaudio_x86.dll"); with(PortAudioDLL) { enum NUM_SECONDS = 5; PaStream* stream; PaError err; Phase phase_data; if ((err = Pa_Initialize()) == paNoError) { writeln("---"); auto numDevices = Pa_GetDeviceCount(); if(numDevices < 0) { printf("ERROR: Pa_CountDevices returned 0x%x\n", numDevices); err = numDevices; goto Lerror; } for(auto i = 0; i < numDevices; i++ ) { auto deviceInfo = Pa_GetDeviceInfo(i); writeln("Device "~to!string(i)~" > "~to!string(deviceInfo.name)~", "~to!string(deviceInfo.maxInputChannels)~", "~to!string(deviceInfo.maxOutputChannels)~", "~to!string(deviceInfo.defaultLowOutputLatency)~","~to!string(deviceInfo.defaultHighOutputLatency)~", "~to!string(deviceInfo.defaultSampleRate)~", "~to!string(deviceInfo.hostApi)); } double sampleRate = 44100; PaStreamParameters* input; if (input != null) { input.device = 0; auto id = Pa_GetDeviceInfo(input.device); input.hostApiSpecificStreamInfo = null; input.channelCount = id.maxInputChannels; input.sampleFormat = paFloat32; input.suggestedLatency = (id.defaultLowInputLatency + id.defaultHighInputLatency)/2; sampleRate = id.defaultSampleRate; } PaStreamParameters* output = new PaStreamParameters(); if (output != null) { output.device = 9; auto od = Pa_GetDeviceInfo(output.device); output.hostApiSpecificStreamInfo = null; output.channelCount = od.maxOutputChannels; output.sampleFormat = paFloat32; output.suggestedLatency = (od.defaultLowOutputLatency +
Re: AutoDLL
Here is a solution that will wrap all extern C functions and allow one to then map them to a dll. auto BuildDLLClassFromCHeader(alias modulename, string name)() { import std.traits, std.algorithm, std.meta; auto s = "extern (C) class " ~name~"\n{\n\timport ___import = "~moduleName!modulename~";\n"; mixin("import "~moduleName!modulename~";"); foreach(m; AliasSeq!(__traits(allMembers, modulename))) { mixin("alias member = " ~ fullyQualifiedName!(modulename) ~ "." ~ m ~ ";"); static if (is(typeof(member) == function)) static if (functionLinkage!member != "C") continue; else s ~= "\tpublic static typeof(___import."~__traits(identifier, member)~")* "~__traits(identifier, member)~";\n"; } return s ~ "}"; } void DllImport(alias T)(string dllName) { import core.sys.windows.windows, std.conv, std.meta; auto dll = LoadLibrary(to!wstring(dllName~"\0").ptr); if (dll == null) assert(0, "Cannot load DLL `"~dllName~"'"); foreach(fname; __traits(derivedMembers, T)) { auto func = GetProcAddress(dll, fname); enum s = "auto p = cast(void**)&"~T.stringof~"."~fname~"; *p = cast(typeof(p))func;"; mixin(s); } } e.g., mixin(BuildDLLClassFromCHeader!(portaudio, "PortAudioDLL")()); DllImport!PortAudioDLL("portaudio_x86.dll"); it generates the following for portaudio.di: extern (C) class PortAudioDLL { import ___import = portaudio; public static typeof(___import.Pa_GetVersion)* Pa_GetVersion; public static typeof(___import.Pa_GetVersionText)* Pa_GetVersionText; public static typeof(___import.Pa_GetErrorText)* Pa_GetErrorText; public static typeof(___import.Pa_Initialize)* Pa_Initialize; public static typeof(___import.Pa_Terminate)* Pa_Terminate; public static typeof(___import.Pa_GetHostApiCount)* Pa_GetHostApiCount; public static typeof(___import.Pa_GetDefaultHostApi)* Pa_GetDefaultHostApi; public static typeof(___import.Pa_GetHostApiInfo)* Pa_GetHostApiInfo; public static typeof(___import.Pa_HostApiTypeIdToHostApiIndex)* Pa_HostApiTypeIdToHostApiIndex; public static typeof(___import.Pa_HostApiDeviceIndexToDeviceIndex)* Pa_HostApiDeviceIndexToDeviceIndex; public static typeof(___import.Pa_GetLastHostErrorInfo)* Pa_GetLastHostErrorInfo; public static typeof(___import.Pa_GetDeviceCount)* Pa_GetDeviceCount; public static typeof(___import.Pa_GetDefaultInputDevice)* Pa_GetDefaultInputDevice; public static typeof(___import.Pa_GetDefaultOutputDevice)* Pa_GetDefaultOutputDevice; public static typeof(___import.Pa_GetDeviceInfo)* Pa_GetDeviceInfo; public static typeof(___import.Pa_IsFormatSupported)* Pa_IsFormatSupported; public static typeof(___import.Pa_OpenStream)* Pa_OpenStream; public static typeof(___import.Pa_OpenDefaultStream)* Pa_OpenDefaultStream; public static typeof(___import.Pa_CloseStream)* Pa_CloseStream; public static typeof(___import.Pa_SetStreamFinishedCallback)* Pa_SetStreamFinishedCallback; public static typeof(___import.Pa_StartStream)* Pa_StartStream; public static typeof(___import.Pa_StopStream)* Pa_StopStream; public static typeof(___import.Pa_AbortStream)* Pa_AbortStream; public static typeof(___import.Pa_IsStreamStopped)* Pa_IsStreamStopped; public static typeof(___import.Pa_IsStreamActive)* Pa_IsStreamActive; public static typeof(___import.Pa_GetStreamInfo)* Pa_GetStreamInfo; public static typeof(___import.Pa_GetStreamTime)* Pa_GetStreamTime; public static typeof(___import.Pa_GetStreamCpuLoad)* Pa_GetStreamCpuLoad; public static typeof(___import.Pa_ReadStream)* Pa_ReadStream; public static typeof(___import.Pa_WriteStream)* Pa_WriteStream; public static typeof(___import.Pa_GetStreamReadAvailable)* Pa_GetStreamReadAvailable; public static typeof(___import.Pa_GetStreamWriteAvailable)* Pa_GetStreamWriteAvailable; public static typeof(___import.Pa_GetSampleSize)* Pa_GetSampleSize; public static typeof(___import.Pa_Sleep)* Pa_Sleep; } and then maps the function pointers to the dll. Should work for other dlls.
Re: auto*
On Thursday, 6 July 2017 at 18:11:13 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 06:10:57PM +, FoxyBrown via Digitalmars-d wrote: Create an auto pointer, handy in some cases and fits in the language as a natural generalization. What's an auto pointer? T is it not obvious? auto x = ... auto* x = ... auto* is the pointerized version of auto. e.g., int x = ... int* x = ... typeof(x) y = ... typeof(x)* y = ... obviously the rhs must be congruent with the type. auto p = // a pointer auto* p = // a double pointer to foo. When having the need to require a pointer to a pointer, it avoids having to specify the type in a verbose way. i.e., the second line above is not valid, but to do it we must either cast to void** or use typeof and such to get the correct type and make a pointer out of it. auto* simplifies all that.
Re: Need simple sound
On Thursday, 6 July 2017 at 14:41:32 UTC, Sebastiaan Koppe wrote: On Thursday, 6 July 2017 at 13:28:26 UTC, FoxyBrown wrote: On Wednesday, 5 July 2017 at 07:21:45 UTC, Sebastiaan Koppe wrote: Sure, see http://code.dlang.org/packages/portaudio So, after a bit of work I can get port audio to work but the callback never seems to be called(no audio, never hits bp). Shows all the devices and seems to run fine otherwise. Tried all the devices I I have. The default stream doesn't work either. The example I posted earlier did work on my Mac. I will try your example + dll loader on Windows later today. Nice loader btw. I went ahead and simplified the DLL import import portaudio; import std.conv, std.stdio; import core.stdc.stdio; alias BOOL = ubyte; alias DWORD = uint; // New void DllImport(alias T)(string dllName) { import core.sys.windows.windows, std.conv, std.meta; auto dll = LoadLibrary(to!wstring(dllName~"\0").ptr); if (dll == null) assert(0, "Cannot load DLL `"~dllName~"'"); foreach(fname; __traits(derivedMembers, T)) { auto func = GetProcAddress(dll, fname); enum s = "auto p = cast(void**)&"~T.stringof~"."~fname~"; *p = cast(typeof(p))func;"; mixin(s); } } extern(C) class PortAudioDLL { public static PaError function() Pa_Initialize; public static PaError function() Pa_Terminate; public static PaHostApiIndex function() Pa_GetHostApiCount; public static PaHostApiIndex function() Pa_GetDefaultHostApi; public static PaDeviceIndex function() Pa_GetDefaultOutputDevice; public static PaDeviceIndex function() Pa_GetDefaultInputDevice; public static PaDeviceIndex function() Pa_GetDeviceCount; public static const(PaHostErrorInfo)* function() Pa_GetLastHostErrorInfo; public static PaDeviceIndex function(PaHostApiIndex hostApi, int hostApiDeviceIndex ) Pa_HostApiDeviceIndexToDeviceIndex; public static PaHostApiIndex function(PaHostApiTypeId type) Pa_HostApiTypeIdToHostApiIndex; public static const(PaHostApiInfo)* function(PaHostApiIndex hostApi) Pa_GetHostApiInfo; public static PaError function(PaStream *stream, PaStreamFinishedCallback streamFinishedCallback) Pa_SetStreamFinishedCallback; public static PaError function(PaStream *stream) Pa_CloseStream; public static PaError function(PaStream** stream, int numInputChannels, int numOutputChannels, PaSampleFormat sampleFormat, double sampleRate, ulong framesPerBuffer, PaStreamCallback streamCallback, void *userData) Pa_OpenDefaultStream; public static PaError function(PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, ulong framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback streamCallback, void *userData) Pa_OpenStream; public static PaError function(const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate) Pa_IsFormatSupported; public static const(PaDeviceInfo)* function(PaDeviceIndex device) Pa_GetDeviceInfo; public static PaError function(PaStream *stream) Pa_StartStream; public static PaError function(PaStream *stream) Pa_StopStream; public static PaError function(PaStream *stream) Pa_AbortStream; public static PaError function(PaStream *stream) Pa_IsStreamStopped; public static void function(long msec) Pa_Sleep; public static PaError function(PaSampleFormat format) Pa_GetSampleSize; public static long function(PaStream* stream) Pa_GetStreamWriteAvailable; public static long function(PaStream* stream) Pa_GetStreamReadAvailable; public static PaError function(PaStream* stream, const void *buffer, ulong frames) Pa_WriteStream; public static PaError function(PaStream* stream, void *buffer, ulong frames) Pa_ReadStream; public static double function(PaStream* stream) Pa_GetStreamCpuLoad; public static PaTime function(PaStream *stream) Pa_GetStreamTime; public static const(PaStreamInfo)* function(PaStream *stream) Pa_GetStreamInfo; public static PaError function(PaStream *stream) Pa_IsStreamActive; public static const(char)* function(PaError errorCode) Pa_GetErrorText; } struct Phase { float left=0, right=0; } bool test = false; extern(C) int sawtooth(const(void)* inputBuffer, void* outputBuffer, size_t framesPerBuffer, const(PaStreamCallbackTimeInfo)* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) { test = true; auto phase = cast(Phase*)userData; auto pout = cast(float*)outputBuffer; enum vol = 0.2f; foreach(i; 0 .. framesPerBuffer) { *pout++ = vol * phase.left; *pout++ = vol * phase.right; phase.left += 0.01f; if (phase.left >= 1.0f) phase.left -= 2.0f; phase.right += 0.03f; if (phase.right >= 1.0f) phase.right -= 2.0f; } return 0; } int
auto*
Create an auto pointer, handy in some cases and fits in the language as a natural generalization.
Re: Need simple sound
On Thursday, 6 July 2017 at 14:41:32 UTC, Sebastiaan Koppe wrote: On Thursday, 6 July 2017 at 13:28:26 UTC, FoxyBrown wrote: On Wednesday, 5 July 2017 at 07:21:45 UTC, Sebastiaan Koppe wrote: Sure, see http://code.dlang.org/packages/portaudio So, after a bit of work I can get port audio to work but the callback never seems to be called(no audio, never hits bp). Shows all the devices and seems to run fine otherwise. Tried all the devices I I have. The default stream doesn't work either. The example I posted earlier did work on my Mac. I will try your example + dll loader on Windows later today. Nice loader btw. The example was drawn pretty much off the portaudio binding you linked. I just fixed it up so that the device parameters were automatically detected for the device I specified(as I got tired of manually typing them and getting errors). The autodll fixed the problem of trying to get the libs to work, which none did and just didn't seem worth the trouble getting to work. whats the real difference between that and the dll with the autoload code? We can bind the dll to the exe at compile time then use import to import it and load it from memory, so it, in effect, is self contained like a lib. I think the autoDLL if done right. I hacked it together and worked easier than I thought but didn't put in the time to make it nice. It could avoid libs all together, not that we need to do that. Still need a h/di file, of course. But why port audio is not calling the callback is beyond me.
Re: AutoDLL
On Thursday, 6 July 2017 at 16:14:18 UTC, Mike Parker wrote: On Thursday, 6 July 2017 at 12:15:57 UTC, FoxyBrown wrote: //pragma(lib, "portaudio_x86.lib"); // Doesn't work because libs are invalid Probably just a OMF/COFF issue. If you try to link with a COFF library while compiling with 32-bit DMD in its default configuration on Windows, you'll get such errors. You'll need to compile with -m32mscoff MS linker instead. Either that, or run coffimplib [1] (doc at [2]) on the portaudio dll. [1] http://ftp.digitalmars.com/coffimplib.zip [2] http://www.digitalmars.com/ctg/coffimplib.html I tried some of that stuff and it didn't work so I gave up and found the code above but it only printed the names so I added the ability to load the functions. I kept on getting that the was invalid. I figured it was more of a mess to try to get the libs right since what if I need to use a coff and omf? Seems like a royal pain in the butt to deal with.
Re: Need simple sound
On Wednesday, 5 July 2017 at 07:21:45 UTC, Sebastiaan Koppe wrote: On Wednesday, 5 July 2017 at 05:34:37 UTC, FoxyBrown wrote: On Tuesday, 4 July 2017 at 20:37:44 UTC, Sebastiaan Koppe wrote: Portaudio is simple as well. And nice cross platform. are there any bindings? Sure, see http://code.dlang.org/packages/portaudio So, after a bit of work I can get port audio to work but the callback never seems to be called(no audio, never hits bp). Shows all the devices and seems to run fine otherwise. Tried all the devices I I have. The default stream doesn't work either. Here is the following code: import portaudio; import std.conv, std.stdio; import core.stdc.stdio; alias BOOL = ubyte; alias DWORD = uint; struct dllimport { string dllName; } template hasAttribute(alias sym, T) { static bool helper() { foreach(a; __traits(getAttributes, sym)) { if(is(a == T) || __traits(compiles, typeof(a)) && is(typeof(a) == T)) return true; } return false; } enum bool hasAttribute = helper(); } template getAttribute(alias sym, T) { static T helper() { foreach(a; __traits(getAttributes, sym)) { static if(is(a == T) || __traits(compiles, typeof(a)) && is(typeof(a) == T)) return a; } assert(0, "attribute " ~ T.stringof ~ " not found"); } enum T getAttribute = helper(); } void doImport(alias T)() { import core.sys.windows.windows, std.conv; bool isDLLLoaded = false; HINSTANCE dll; foreach(m; __traits(allMembers, T)) { static if(__traits(compiles, typeof(__traits(getMember, T, m { static if(hasAttribute!(__traits(getMember, T, m), dllimport)) { auto dllName = getAttribute!(__traits(getMember, T, m), dllimport).dllName; if (!isDLLLoaded) { writeln("Loading DLL `"~dllName~"'..."); isDLLLoaded = true; dll = LoadLibrary(to!wstring(dllName~"\0").ptr); if (dll == null) { // ERROR, handle writeln("Error, aborting!"); return; } } auto q = GetProcAddress(dll, m); mixin(m~" = cast(typeof("~m~"))q;"); //func(m, getAttribute!(__traits(getMember, T, m), dllimport).dllName, cast(void**)&__traits(getMember, T, m)); } } } } mixin template DllImportFunctions() { struct DllImporter { shared static this() { doImport!(__traits(parent, DllImporter))(); } static loadFunction(string name, const(char)[] dllName, void** addr) { printf("import %.*s from %.*s into %llx\n", name.length, name.ptr, dllName.length, dllName.ptr, addr); } } } extern(C) @dllimport("portaudio_x86.dll") __gshared { PaError function() Pa_Initialize; PaError function() Pa_Terminate; PaHostApiIndex function() Pa_GetHostApiCount; PaHostApiIndex function() Pa_GetDefaultHostApi; PaDeviceIndex function() Pa_GetDefaultOutputDevice; PaDeviceIndex function() Pa_GetDefaultInputDevice; PaDeviceIndex function() Pa_GetDeviceCount; const(PaHostErrorInfo)* function() Pa_GetLastHostErrorInfo; PaDeviceIndex function(PaHostApiIndex hostApi, int hostApiDeviceIndex ) Pa_HostApiDeviceIndexToDeviceIndex; PaHostApiIndex function(PaHostApiTypeId type) Pa_HostApiTypeIdToHostApiIndex; const(PaHostApiInfo)* function(PaHostApiIndex hostApi) Pa_GetHostApiInfo; PaError function(PaStream *stream, PaStreamFinishedCallback streamFinishedCallback) Pa_SetStreamFinishedCallback; PaError function(PaStream *stream) Pa_CloseStream; PaError function(PaStream** stream, int numInputChannels, int numOutputChannels, PaSampleFormat sampleFormat, double sampleRate, ulong framesPerBuffer, PaStreamCallback streamCallback, void *userData) Pa_OpenDefaultStream; PaError function(PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, ulong framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback streamCallback, void *userData) Pa_OpenStream; PaError function(const PaStreamParameters
AutoDLL
A DLL Loader prototype that loads DLL's, just specify the declaration. Probably should be worked up so it is easy to load DLL's. Example: import portaudio; import std.conv, std.stdio; import core.stdc.stdio; //pragma(lib, "portaudio_x86.lib"); // Doesn't work because libs are invalid alias BOOL = ubyte; alias DWORD = uint; struct dllimport { string dllName; } template hasAttribute(alias sym, T) { static bool helper() { foreach(a; __traits(getAttributes, sym)) { if(is(a == T) || __traits(compiles, typeof(a)) && is(typeof(a) == T)) return true; } return false; } enum bool hasAttribute = helper(); } template getAttribute(alias sym, T) { static T helper() { foreach(a; __traits(getAttributes, sym)) { static if(is(a == T) || __traits(compiles, typeof(a)) && is(typeof(a) == T)) return a; } assert(0, "attribute " ~ T.stringof ~ " not found"); } enum T getAttribute = helper(); } void doImport(alias T)() { import core.sys.windows.windows, std.conv; bool isDLLLoaded = false; HINSTANCE dll; foreach(m; __traits(allMembers, T)) { static if(__traits(compiles, typeof(__traits(getMember, T, m { static if(hasAttribute!(__traits(getMember, T, m), dllimport)) { auto dllName = getAttribute!(__traits(getMember, T, m), dllimport).dllName; if (!isDLLLoaded) { writeln("Loading DLL `"~dllName~"'..."); isDLLLoaded = true; dll = LoadLibrary(to!wstring(dllName~"\0").ptr); if (dll == null) { // ERROR, handle writeln("Error, aborting!"); return; } } auto q = GetProcAddress(dll, m); mixin(m~" = cast(typeof("~m~"))q;"); //func(m, getAttribute!(__traits(getMember, T, m), dllimport).dllName, cast(void**)&__traits(getMember, T, m)); } } } } mixin template DllImportFunctions() { struct DllImporter { shared static this() { doImport!(__traits(parent, DllImporter))(); } static loadFunction(string name, const(char)[] dllName, void** addr) { printf("import %.*s from %.*s into %llx\n", name.length, name.ptr, dllName.length, dllName.ptr, addr); } } } extern(Windows) @dllimport("portaudio_x86.dll") __gshared { PaError function() Pa_Initialize; PaError function() Pa_Terminate; PaHostApiIndex function() Pa_GetHostApiCount; PaHostApiIndex function() Pa_GetDefaultHostApi; PaDeviceIndex function() Pa_GetDefaultOutputDevice; PaDeviceIndex function() Pa_GetDefaultInputDevice; PaDeviceIndex function() Pa_GetDeviceCount; const(PaHostErrorInfo)* function() Pa_GetLastHostErrorInfo; PaDeviceIndex function(PaHostApiIndex hostApi, int hostApiDeviceIndex ) Pa_HostApiDeviceIndexToDeviceIndex; PaHostApiIndex function(PaHostApiTypeId type) Pa_HostApiTypeIdToHostApiIndex; const(PaHostApiInfo)* function(PaHostApiIndex hostApi) Pa_GetHostApiInfo; PaError function(PaStream *stream, PaStreamFinishedCallback streamFinishedCallback) Pa_SetStreamFinishedCallback; PaError function(PaStream *stream) Pa_CloseStream; PaError function(PaStream** stream, int numInputChannels, int numOutputChannels, PaSampleFormat sampleFormat, double sampleRate, ulong framesPerBuffer, PaStreamCallback streamCallback, void *userData) Pa_OpenDefaultStream; PaError function(PaStream** stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, ulong framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback streamCallback, void *userData) Pa_OpenStream; PaError function(const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate) Pa_IsFormatSupported; const(PaDeviceInfo)* function(PaDeviceIndex device) Pa_GetDeviceInfo; PaError function(PaStream *stream) Pa_StartStream; PaError function(PaStream *stream) Pa_StopStream; PaError function(PaStream *stream) Pa_AbortStream; PaError function(PaStream
Re: Need simple sound
On Wednesday, 5 July 2017 at 07:21:45 UTC, Sebastiaan Koppe wrote: On Wednesday, 5 July 2017 at 05:34:37 UTC, FoxyBrown wrote: On Tuesday, 4 July 2017 at 20:37:44 UTC, Sebastiaan Koppe wrote: Portaudio is simple as well. And nice cross platform. are there any bindings? Sure, see http://code.dlang.org/packages/portaudio I can't seem to get this to work. Are there any windows dll's or libs that work that are not outdated?
Re: GtkD nothing
Unfortunately, importing that module seems to throw an error for some insane reason. Error 42: Symbol Undefined _D3gtk6All12__ModuleInfoZ (gtk.AllGTK.__ModuleInfo) without importing it in to the project(but directly importing all the other modules works fine, e.g., copying and pasting).
Re: GtkD nothing
The module All in GtkD\generated\Gtkd\gtk will allow importing everything, e.g. import gtk = gtk.All; gtk.MainWindow etc. All.d-- module gtk.All; public import gtk.AboutDialog; public import gtk.AccelGroup; public import gtk.AccelLabel; public import gtk.AccelMap; public import gtk.Accessible; public import gtk.Action; public import gtk.ActionableIF; public import gtk.ActionableT; public import gtk.ActionBar; public import gtk.ActionGroup; public import gtk.ActivatableIF; public import gtk.ActivatableT; public import gtk.Adjustment; public import gtk.Alignment; public import gtk.AppChooserButton; public import gtk.AppChooserDialog; public import gtk.AppChooserIF; public import gtk.AppChooserT; public import gtk.AppChooserWidget; public import gtk.Application; public import gtk.ApplicationWindow; public import gtk.Arrow; public import gtk.ArrowAccessible; public import gtk.AspectFrame; public import gtk.Assistant; public import gtk.Bin; public import gtk.BindingEntry; public import gtk.BindingSet; public import gtk.BooleanCellAccessible; public import gtk.Border; public import gtk.Box; public import gtk.BuildableIF; public import gtk.BuildableT; public import gtk.Builder; public import gtk.Button; public import gtk.ButtonAccessible; public import gtk.ButtonBox; public import gtk.Calendar; public import gtk.CellAccessible; public import gtk.CellAccessibleParentIF; public import gtk.CellAccessibleParentT; public import gtk.CellArea; public import gtk.CellAreaBox; public import gtk.CellAreaClass; public import gtk.CellAreaContext; public import gtk.CellEditable; public import gtk.CellEditableIF; public import gtk.CellEditableT; public import gtk.CellLayoutIF; public import gtk.CellLayoutT; public import gtk.CellRenderer; public import gtk.CellRendererAccel; public import gtk.CellRendererClass; public import gtk.CellRendererCombo; public import gtk.CellRendererPixbuf; public import gtk.CellRendererProgress; public import gtk.CellRendererSpin; public import gtk.CellRendererSpinner; public import gtk.CellRendererText; public import gtk.CellRendererToggle; public import gtk.CellView; public import gtk.CheckButton; public import gtk.CheckMenuItem; public import gtk.CheckMenuItemAccessible; public import gtk.Clipboard; public import gtk.ColorButton; public import gtk.ColorChooserDialog; public import gtk.ColorChooserIF; public import gtk.ColorChooserT; public import gtk.ColorChooserWidget; public import gtk.ColorSelection; public import gtk.ColorSelectionDialog; public import gtk.ComboBox; public import gtk.ComboBoxAccessible; public import gtk.ComboBoxText; public import gtk.Container; public import gtk.ContainerAccessible; public import gtk.ContainerCellAccessible; public import gtk.ContainerClass; public import gtk.CssProvider; public import gtk.CssSection; public import gtk.Dialog; public import gtk.DragAndDrop; public import gtk.DrawingArea; public import gtk.EditableIF; public import gtk.EditableT; public import gtk.Entry; public import gtk.EntryAccessible; public import gtk.EntryBuffer; public import gtk.EntryCompletion; public import gtk.EventBox; public import gtk.EventController; public import gtk.Expander; public import gtk.ExpanderAccessible; public import gtk.FileChooserButton; public import gtk.FileChooserDialog; public import gtk.FileChooserIF; public import gtk.FileChooserNative; public import gtk.FileChooserT; public import gtk.FileChooserWidget; public import gtk.FileFilter; public import gtk.Fixed; public import gtk.FlowBox; public import gtk.FlowBoxAccessible; public import gtk.FlowBoxChild; public import gtk.FlowBoxChildAccessible; public import gtk.FontButton; public import gtk.FontChooserDialog; public import gtk.FontChooserIF; public import gtk.FontChooserT; public import gtk.FontChooserWidget; public import gtk.FontSelection; public import gtk.FontSelectionDialog; public import gtk.Frame; public import gtk.FrameAccessible; public import gtk.Gesture; public import gtk.GestureDrag; public import gtk.GestureLongPress; public import gtk.GestureMultiPress; public import gtk.GesturePan; public import gtk.GestureRotate; public import gtk.GestureSingle; public import gtk.GestureSwipe; public import gtk.GestureZoom; public import gtk.GLArea; public import gtk.Gradient; public import gtk.Grid; public import gtk.HandleBox; public import gtk.HBox; public import gtk.HButtonBox; public import gtk.HeaderBar; public import gtk.HPaned; public import gtk.HScale; public import gtk.HScrollbar; public import gtk.HSeparator; public import gtk.HSV; public import gtk.IconFactory; public import gtk.IconInfo; public import gtk.IconSet; public import gtk.IconSize; public import gtk.IconSource; public import gtk.IconTheme; public import gtk.IconView; public import gtk.IconViewAccessible; public import gtk.Image; public import gtk.ImageAccessible; public import gtk.ImageCellAccessible; public import gtk.ImageMenuItem; public import gtk.IMContext; public import gtk.IMContextSimple; public import
Re: GtkD nothing
On Thursday, 6 July 2017 at 01:06:38 UTC, FoxyBrown wrote: On Thursday, 6 July 2017 at 01:03:11 UTC, FoxyBrown wrote: On Thursday, 6 July 2017 at 00:51:40 UTC, FoxyBrown wrote: [...] Running it from the command line showed it wasn't finding the gtk dll. The path variable is set up correctly. I copied the bin dir to the exe and it ran and worked except for missing icons. Why is gtkD not finding gtk+ even though it is clearly in the path and correct? Copying over the share dir gets it to work but surely all this is avoidable? So, while the setup isn't smooth and not finding everything, do I really have to import every ui element or can I just import the entire gtk?
Re: GtkD nothing
On Thursday, 6 July 2017 at 01:03:11 UTC, FoxyBrown wrote: On Thursday, 6 July 2017 at 00:51:40 UTC, FoxyBrown wrote: [...] Running it from the command line showed it wasn't finding the gtk dll. The path variable is set up correctly. I copied the bin dir to the exe and it ran and worked except for missing icons. Why is gtkD not finding gtk+ even though it is clearly in the path and correct? Copying over the share dir gets it to work but surely all this is avoidable?
Re: GtkD nothing
On Thursday, 6 July 2017 at 00:51:40 UTC, FoxyBrown wrote: import gtk.MainWindow; import gtk.Label; import gtk.Main; import std.stdio; pragma(lib, "C:\\DLang\\GtkD\\x86\\gtkd.lib"); void main(string[] args) { Main.init(args); MainWindow win = new MainWindow("Hello World"); win.setDefaultSize(200, 100); win.add(new Label("Hello World")); win.showAll(); Main.run(); getchar(); } Did all the steps, had to switch over from the 64-bit to the 32-bit dll of gtk+ to avoid errors(since i couldn't get gtkD to compile for 64-bit). The above code(copied from site) simply runs and exists, I added the getchar but it doesn't seem to be executed. a BP on the first line is never reached, no errors, nothing, to help diagnose the issues. Any ideas? Running it from the command line showed it wasn't finding the gtk dll. The path variable is set up correctly. I copied the bin dir to the exe and it ran and worked except for missing icons. Why is gtkD not finding gtk+ even though it is clearly in the path and correct?
GtkD nothing
import gtk.MainWindow; import gtk.Label; import gtk.Main; import std.stdio; pragma(lib, "C:\\DLang\\GtkD\\x86\\gtkd.lib"); void main(string[] args) { Main.init(args); MainWindow win = new MainWindow("Hello World"); win.setDefaultSize(200, 100); win.add(new Label("Hello World")); win.showAll(); Main.run(); getchar(); } Did all the steps, had to switch over from the 64-bit to the 32-bit dll of gtk+ to avoid errors(since i couldn't get gtkD to compile for 64-bit). The above code(copied from site) simply runs and exists, I added the getchar but it doesn't seem to be executed. a BP on the first line is never reached, no errors, nothing, to help diagnose the issues. Any ideas?
rdmd issues
rdmd -m64 Build.d Error: can't run 'C:\Program Files\VS\VC\Tools\MSVC\14.10.25017\bin\HostX64\x64', check PATH The path exists, but since it doesn't tell me what it is trying to run, I have no clue. The path contains link.exe.
Re: Need simple sound
On Tuesday, 4 July 2017 at 20:37:44 UTC, Sebastiaan Koppe wrote: On Monday, 3 July 2017 at 08:55:20 UTC, Martin Tschierschke wrote: Hello for a simple game I would like to add some very simple sound, not much different than the beeps of "PAC Man". Is there anything I can use for this? Portaudio is simple as well. And nice cross platform. are there any bindings?
Re: Finding all the interfaces and their inheritance relationships at runtime
On Monday, 3 July 2017 at 20:45:19 UTC, bauss wrote: On Monday, 3 July 2017 at 13:54:42 UTC, Jean-Louis Leroy wrote: I know how to find all the classes: foreach (mod; ModuleInfo) { foreach (c; mod.localClasses) { // use c.base to construct inheritance graph } } Can I do the same with all the interfaces? Looking at object.d gives no clue... Is there a reason you need to do it with runtime and can't use __traits? He didn't say *with* runtime but *at*. Changes the whole meaning ;)
Re: Strange Bug in LDC vs DMD
On Friday, 30 June 2017 at 20:13:37 UTC, H. S. Teoh wrote: On Fri, Jun 30, 2017 at 07:57:22PM +, FoxyBrown via Digitalmars-d-learn wrote: [...] [...] Um... the docs explicit say that dirEntries is lazy, did you not see that? [...] It is possible that dmd has the same problem but I did not see it. What I did was develop it using dmd then once it was working went to release ldc and saw that it immediately did not have the same results and the results were wrong. Since I was debugging it the whole time and it was working fine with dmd, I simply assumed dmd was working. Since it is a lazy range, I'm sure that is the problem.
Natural Sort optimzation
Spent the last hour trying to get a natural sort. Ended up having to create my own(not sure if it's 100% correct though but works in practice). The Rosetta one is not correct. Here is my implementation, anyone care to perfect it? // Compares the strings a and b numerically, e.g., "04038284" and "02" returns 1, the first is larger. int compareStringNum(string a, string b) { // Remove leading 0's a = a.stripLeft('0'); b = b.stripLeft('0'); if (a.length > b.length) return 1; if (a.length < b.length) return -1; auto m = a.length; for(int i = 0; i < m; i++) { auto qqx = a[i]; auto qqy = b[i]; // Assume ascii comparision holds, i.e., '0' < '1' < ... < '9' if (a[i] > b[i]) return 1; if (a[i] < b[i]) return -1; } return 0; } string[] naturalSort(string[] arr) /*pure @safe*/ { alias myComp = (x, y) { auto ml = min(x.length, y.length)-1; auto ofsx = -1; auto ofsy = -1; auto numx_found = -1; auto numy_found = -1; for(int i = 0; i < ml; i++) { ofsx++; ofsy++; // If we have not found any numbers(that are not the same) and we have a difference, the strings must be different, fall back on standard character comparer if (!isDigit(x[ofsx]) && !isDigit(y[ofsy]) && x[ofsx] != y[ofsy] && numx_found < 0 && numy_found < 0) return x[ofsx] > y[ofsy]; // We are at a position in the string where either we are at the end of a digit sequence or the characters have been identical up to this point if (isDigit(x[ofsx]) && numx_found < 0) numx_found = ofsx; if (isDigit(y[ofsy]) && numy_found < 0) numy_found = ofsy; if (!isDigit(x[ofsx]) && !isDigit(y[ofsy]) && numx_found >= 0 && numy_found >= 0) { auto numx = x[numx_found..ofsx]; auto numy = y[numy_found..ofsy]; auto res = compareStringNum(numx, numy); if (res != 0) return (res != 1); } if (!isDigit(x[ofsx]) && !isDigit(y[ofsy])) { numx_found = -1; numy_found = -1; } else { if (!isDigit(x[ofsx]) && numx_found >= 0) ofsx--; if (!isDigit(y[ofsy]) && numy_found >= 0) ofsy--; } } return x > y; }; auto x = arr.sort!(myComp).release; return x; }
Re: Strange Bug in LDC vs DMD
On Friday, 30 June 2017 at 17:32:33 UTC, H. S. Teoh wrote: On Fri, Jun 30, 2017 at 12:50:24PM +, FoxyBrown via Digitalmars-d-learn wrote: I am using dirEntries to iterate over files to rename them. I am renaming them in a loop(will change but added code for testing). In DMD the renaming works but in LDC the renaming fails. It fails in a way that I can't quite tell and I cannot debug because visual D is not working properly for LDC. The code essentially look like the following: auto dFiles = dirEntries(loc, mask, _mode); foreach (d; dFiles) { auto newName = Recompute(d.name) writeln(newName); rename(d.name, newName); } but when I comment out rename, it works under LDC. The funny thing is, newName is printed wrong so Recompute is effected by the rename. This shouldn't occur. [...] This sounds very strange. What exactly do you mean by "newName is printed wrong"? Do you mean that somehow it's getting affected by the *subsequent* rename()? That would be truly strange. Or do you mean that newName doesn't match what you expect Recompute to do given d.name? Perhaps you should also print out d.name along with newName just to be sure? Do you have a reduced code example that's compilable/runnable? It's rather hard to tell what's wrong based on your incomplete snippet. T No, if I simply comment out the rename line, then the writeln output changes. Simple as that. No other logic changes in the code. This means that the rename is affecting the output. The recompute code gets the filename, does a computation on it, then returns it.. prints it out, then renames that file to the newly computed file name. The only way this can happen is if the rename command is somehow feeding back in to the algorithm. Since the problem goes away when I pre-compute dirEntries, it suggests that dirEntries is being lazily computed. If that is the case, then the problem is easily understood: The file gets renamed, dirEntries reiterates over the file, then it gets recomputed again, but this time the result is bogus because it is a double recompute, which is meaningless in this program. I'm pretty sure that the analysis above is correct, that is, dirEntries is lazy and ends up picking up the renamed file. This is sort of like removing an element in an array while iterating over the array. The odd thing is, is that DMD does not produce the same result. I do not know if there is a different in the LDC vs DMD dirEntries code(or lazily evaluated code in general) or if it has to do with speed(possibly the renames are cached and do not show up immediately to dirEntries with the slower DMD?). I do not have any simplified code and I'm moving on from here. It should be easy to mock something up. The main thing to do is to rename the files based on something in the file name. e.g., suppose you have the files 1,2,3,4,5 (that is there names) and extract and multiply the filenames by 10. (that is your recompute function). You should end up with 10,20,30,40,50. But if the cause of issue I'm describing is in fact true, one don't necessarily get that because some files will be iterated more than once. e.g., maybe 10, 100, 1000, 20, 200, 30, 40, 50, 500. I am doing it over a lot of files btw, but that is essentially what is going on. The example above should be easy to do since one can simply to!int the filename and then multiply it by 10 and then rename that. I have moved on to avoid dirEntries completely and simply use the os directory listing function manually to extract the data but this should be investigated as it if it the behavior is what I am describing, a serious bug exists somewhere. (if someone could confirm that dirEntries is a lazy range, then it would explain the problem, but not necessarily why dmd and ldc differ, (dmd seeming to function as expected)).
Re: Strange Bug in LDC vs DMD
On Friday, 30 June 2017 at 15:07:29 UTC, Murzistor wrote: On Friday, 30 June 2017 at 12:50:24 UTC, FoxyBrown wrote: The funny thing is, newName is printed wrong so Recompute is effected by the rename. Does LDC use Unicode? Or, maybe, standard library under LDC does not support Unicode - then it is a serious bug. Do you use any non-ASCII symbols? Maybe, the Recompute() function returns a non-unicode string under LDC? None of these reasons make sense. They do not take in to account that simply pre-evaluating dirEntries causes it to work nor the fact that I said that commenting the rename out also works.
Strange Bug in LDC vs DMD
I am using dirEntries to iterate over files to rename them. I am renaming them in a loop(will change but added code for testing). In DMD the renaming works but in LDC the renaming fails. It fails in a way that I can't quite tell and I cannot debug because visual D is not working properly for LDC. The code essentially look like the following: auto dFiles = dirEntries(loc, mask, _mode); foreach (d; dFiles) { auto newName = Recompute(d.name) writeln(newName); rename(d.name, newName); } but when I comment out rename, it works under LDC. The funny thing is, newName is printed wrong so Recompute is effected by the rename. This shouldn't occur. Now, dirEntries is a range, so I'm curious if the recomputation is occurring after the rename(if it did then the recomputation would be invalid and produce the results it is producing)? When I forcably convert dirEntries in to an array(manually, unfortunately, as I can't seem to use array() on dirEntries), everything works). struct file { public string name; } auto dFiles = dirEntries(loc, mask, _mode); file[] files; foreach (d; dFiles) { file f; f.name = d.name; files ~= f; } foreach (d; files) { auto newName = Recompute(d.name) writeln(newName); rename(d.name, newName); } While it works, the main issue is that a different behavior is observed between DMD and LDC in the first case. It would be nice to know how to simplify the code though so "lazy" evaluation of dirEntries did not occur.
Re: Let's paint those bikesheds^Werror messages!
On Tuesday, 27 June 2017 at 14:32:28 UTC, Vladimir Panteleev wrote: As has been announced, DMD now has colorized syntax highlighting in error messages: http://forum.dlang.org/post/of9oao$230j$1...@digitalmars.com With 2.075's release near, now would be a good time to decide on a nice color palette that looks fine on most terminals. So, please vote: https://github.com/dlang/dmd/pull/6943 Obligatory: - Yes, not everyone likes colors. You can turn all colors off with a command-line switch. - Yes, everyone agrees that having all colors be configurable would be good. We still need defaults that are going to look OK on most terminals. - Yes, no matter what colors we choose, they're going to look bad on some terminal somewhere. Let's worry about the major platforms' most common terminals for now. This will be a nightmare if you do not allow it to be configurable! Hard coding anything is very bad when others are will use it. Make a default color scheme that works for the majority as you are, but then allow it to be easily changed. E.g., it can read a config file or passed through the command line(possibly different color schemes can be selected). Do it right or suffer the consequences!
Re: D error messages for function call mismatches
On Tuesday, 27 June 2017 at 15:01:41 UTC, Adam D. Ruppe wrote: On Tuesday, 27 June 2017 at 14:29:05 UTC, FoxyBrown wrote: D's error messaging is terrible in some ways. I am trying to get some code to work and this is the error: I agree, that error message is terrible, and that's why I have a PR open to change it. But this specific case is weird to me too. stb_truetype.d is a port from C code, and I use it without any compile errors. Did you modify the code? Find the bug! Even worse, I don't even see an error in that error message. The arguments it lists look acceptable. Hi Adam, Yeah, I don't know, I think I had it working before but now it seems a lot of your code is not working. I did not change the std_truetype.d file. Just to make sure I copied and pasted the git source in to the original. alias STBTT_sort = core.stdc.stdlib.qsort; Is it possible that core.stdc.stdlib.qsort changed? voidqsort(scope void* base, size_t nmemb, size_t size, _compare_fp_t compar); arsd\stb_truetype.d(1251): Error: function core.stdc.stdlib.qsort (scope void* base, uint nmemb, uint size, extern (C) int function(scope const(void*), scope const(void*)) @system compar) is not callable using argument types (void*, uint, uint, extern (C) int function(const(void*) p, const(void*) q)) I changed your variables to size_t and they obviously match. The things that don't match are the scope's. qsort(scope void* base, uint nmemb, uint size, extern (C) int function(scope const(void*), scope const(void*)) @system compar) (void*, uint, uint, extern (C) int function(const(void*) p, const(void*) q)) I am also getting a run time error with your png loading module. void popFront () { bufpos = 0; while (plpos != plpos.max && bufpos < chunkSize) { // do we have some bytes in zstream? if (zs.avail_in > 0) { // just unpack zs.next_out = cast(typeof(zs.next_out))(buffer.ptr+bufpos); int rd = chunkSize-bufpos; zs.avail_out = rd; auto err = inflate(, Z_SYNC_FLUSH); if (err != Z_STREAM_END && err != Z_OK) throw new Exception("PNG unpack error"); Errors out with unpack error. This code used to work so it is probably on my system.
D error messages for function call mismatches
D's error messaging is terrible in some ways. I am trying to get some code to work and this is the error: arsd\stb_truetype.d(1246): Error: function core.stdc.stdlib.qsort (scope void* base, uint nmemb, uint size, extern (C) int function(scope const(void*), scope const(void*)) @system compar) is not callable using argument types (void*, int, uint, extern (C) int function(const(void*) p, const(void*) q)) Find the bug! Why can't D just dive a bit further and tell me the actual parameter(s) that it failing on? It obviously knows this as it has to check each one to know if there is an error. It should make it clear so I don't have to hunt and peck for the error. These lines don't always get wrapped in all cases so it is a scrollfest trying to find it. Do the lead programmers for D use Visual D? Or do they use a specific tool chain that exhibits a specific behavior that they assume translates in to every other case?
Clean Executable
How can we clean an exe from the junk library functions that are not actually used by an app. e.g., a hello world program shouldn't be 500+kb. I release there are necessary extras like the GC, but hell, in a hello world program is it even necessary? Does Writeln even use the GC to display a single string? Seems like D just does not optimize the binaries size. I know it's only 500kb, but still.
Re: Windows/Android/Mac/RaspberryPi/Linux/ARM/FPGA/ASIC/DSP/uC
On Saturday, 24 June 2017 at 18:51:44 UTC, Johan Engelen wrote: On Saturday, 24 June 2017 at 18:16:46 UTC, FoxyBrown wrote: [...] Yes indeed. LDC will output the IR when you use the `-output-ll` (human readable) or `-output-bc` (binary representation) compile switches. [...] In theory, yes indeed. What may be important is that the LLVM versions match (the LLVM version used to build LDC, and the LLVM version of that 8051 fork). With every new LLVM version, the IR may change in subtle ways... [...] As far as I know, GCC also uses an IR (it's used for LTO). -Johan Why, then, doesn't anything that targets llvm simply target everything else? D is not just for the ones listed but also for many other platforms? is it simply because no one has implemented the transformations to prove it works?
Re: Windows/Android/Mac/RaspberryPi/Linux/ARM/FPGA/ASIC/DSP/uC
On Friday, 23 June 2017 at 19:56:17 UTC, Joakim wrote: On Friday, 23 June 2017 at 19:03:01 UTC, FoxyBrown wrote: [...] The ldc wiki page has a rudimentary version of what you're looking for, listing all platforms worked on and some idea of how well they're supported: https://wiki.dlang.org/LDC Thanks, it's a start. Dmd will likely never target the vast majority of the platforms you list, so it will depend on the gdc and ldc teams doing it. I'm not too worried about dmd, I am mainly interested in simply a way. D is a nice language, so being able to use it, regardless of which compiler, is the goal. Also, I'm looking at submitting a pull with my last ldc CMake patch to cross-compile the stdlib for Android/ARM and generalizing it for other platforms too: https://gist.github.com/joakim-noah/d74af3cf1355492557a9c56ef1bf2636 Once that's in, building a cross-compiled stdlib for several platforms should be as simple as setting some flags with the location of a C cross-compiler and any C/linker flags you need, then running the same cmake/make combo that you use to build a native stdlib today. No modifications are needed to ldc itself for well-supported platforms, as ldc is always a cross-compiler by default. For example, kinke used the new llvm linker, lld, to cross-compile Windows/x64 binaries from linux/x64 by using the stock ldc compiler. The instructions for how he did it are linked from the changelog for the latest ldc 1.3 beta2: https://github.com/ldc-developers/ldc/pull/2142#issuecomment-304472412 Finally, the latest ldc 1.3 betas for the first time include the llvm code-generation target backends for various other CPUs, like ARM or PowerPC, whereas before ldc only bothered to compile in the x86/x64 backends, as those were the only stdlibs it distributed: [joakim@localhost ~]$ ./ldc2-1.3.0-beta2-linux-x86_64/bin/ldc2 --version LDC - the LLVM D compiler (1.3.0-beta2): based on DMD v2.073.2 and LLVM 4.0.0 built with LDC - the LLVM D compiler (1.3.0-beta2) Default target: x86_64-unknown-linux-gnu Host CPU: broadwell http://dlang.org - http://wiki.dlang.org/LDC Registered Targets: aarch64- AArch64 (little endian) aarch64_be - AArch64 (big endian) arm- ARM arm64 - ARM64 (little endian) armeb - ARM (big endian) ppc32 - PowerPC 32 ppc64 - PowerPC 64 ppc64le- PowerPC 64 LE thumb - Thumb thumbeb- Thumb (big endian) x86- 32-bit X86: Pentium-Pro and above x86-64 - 64-bit X86: EM64T and AMD64 Not very useful right now unless you're doing bare-metal programming on those newly added architectures, because the cross-compiled stdlibs are not included and there's no easy way to generate them, but we could also put out separate tarfiles with the cross-compiled stdlibs (separated only to save space in the compiler download for those who don't want them), just as kinke used the ldc stdlib compiled for Windows/x64 on linux/x64 when cross-compiling. Just last night, I was thinking about some easy way to let ldc users cross-compile the stdlib themselves from the regular ldc download, and I thought of doing it with dub, the D package manager, since we now distribute dub alongside ldc. However, I don't know how feasible this is with dub, needs to be looked into. Nice to know it's being worked on. I am not really familiar with llvm but it seems like it can be quite useful. I'm I correct that basically llvm is an intermediate representation(sorta like C#/VBS/F#/etc's IR)? This means that one simply needs a front end that converts the source code to llvm's IR and then a back end that converts the IR to targets binary? For example, a quick search for llvm and 8051 gives this: https://github.com/AndreaCorallo/llvm-i8051 Since, I assume(since there is no documentation describing what it does) is a backend compiler for llvm's IR to 8051, we can go from LDC to LLVM to 8051? In theory, of course. This is all bare metal, of course. Is GCC effectively the same(although the IR is skipped?)? Thanks.
Targetting the 8051
Is it possible? Using LDC or GCC? I do not need any libraries, druntime, etc. Just bare bones with the nice D meta features(templates, etc).
Windows/Android/Mac/RaspberryPi/Linux/ARM/FPGA/ASIC/DSP/uC
Hi, I will be developing some hardware and software that will need to be portable across a multitude of systems. At first, I will develop some of the non-specific infrastructural code base on windows for convenience. These involve the GUI, overall structure, etc. I think will need to move in to more mobile aspects such as the android and Raspberry Pi which will allow me to start to integrate and work with the future hardware based parts of this system. At this point I am in the setup stages that will organize and formulate a proper plan of action. I am aware that D works for Windows/Linux/Mac and has some Raspberry Pi and android/arm support with very little FPGA/ASIC/DSP/uC support. I hope, by the time that I get in to the hardware layers that D will have advanced further down the line on them. My understanding is that DMD is only applicable for the 3 main platforms, and this is fine for now as that is where I'll start. LDC is starting to progress on ARM/android and I have seen someone write a to use D on FPGA through a transformation process. Some work has been done with some lower level uC's such as the PIC and ARM processors. Now that GDC is in the works, I assume that will open up even more doors. Because this is a long term project(10+ years) and involves many different systems, subsystems, architectures, and so forth, organization is key for success. The problem I have with the choice of D over C/C++, at the moment, is in it's knowledge base. Most of the advancements for the different platforms are done by individuals with their own unique goals and motivations in mind. There is very little organized structure to the overall development. Finding information for specific aspects and requirements involves hunting down the appropriate information. Usually it is forum posts and link fishing, usually outdated. Structured documentation is key for efficient and successful progress, which I find D to be lacking in. While library functionality is documented and adequate, the architectural issues and development is not. Is there any hope of seeing a unified structured interface to the different platforms that D is starting to be developed on rather than having to hunt and peck for the answers? If not, may I suggest, at a minimum, some type of hierarchy based solution that involves all the major design applications of D with the ability to cross-reference, date, comment, and modify? A sort of wiki but with a bit more hierarchical structure. D Cross-Platform Compilers ... GDC ... Library ... ... Windows Compiler ... Compiling ... ... Library ... Compiling ... Documentation ... Wi32 API ... Problems ... Functions ... Misc ... Uncategorized ... ... ... ... DSP ... Progress ... ... The idea is that one can delve in to the hierarchy and find whatever info they want or add to it if it is not there so that someone else can find it. At some point, most of what D can do is found in the hierarchy, which, as we all know, only requires around O(log2(n)) search time(rather than O(n^m) for googling topics and link fishing). At some point, this hierarchy becomes very efficient at representing the information we all are searching for rather than a flat random access type of list. The point is to design such an interface and let users like me fill it out and as time goes on, finding relevant information becomes quicker and quicker. For proper design, meta-information must be used to it's fullest. (Tags, date stamping, ratings, relevancy, cross-references, etc) Or, perhaps, we already have something this powerful in the works?