Re: using this instead of typeof(this)

2013-02-26 Thread Ben Davis

On 26/02/2013 18:41, bearophile wrote:

Kenji Hara:


auto return is a little different with others. To infer return type,
the method body is aggressively analyzed in compilation.


So that usage of auto sounds like something to avoid if you want D
compiler to compile quickly a lot of code.


I suspect it doesn't matter actually. The semantic analysis of the 
function body is going to have to happen anyway. It all depends on 
whether the compiler does an extra pass which it throws away the work of 
- which seems fairly unlikely to me (having written a couple of Java 
type resolvers I could have done without having to write xD).


Re: scope(exit) stack = double free or corruption (fasttop) ... help?

2013-02-26 Thread Ben Davis

On 26/02/2013 06:21, Charles Hixson wrote:

On 02/24/2013 05:39 PM, H. S. Teoh wrote:

On Sun, Feb 24, 2013 at 03:14:01PM -0800, Charles Hixson wrote:

Given a struct with:

~this()
{  close();}

voidclose()
{  if(currentKey !is null)currentKey=null;
if(cursor is null)return;
tcbdbcurdel(cursor);
}

and:

   scope (exit)if (bdb !is null)  tcbdbclose(bdb);
   //scope(exit)cur.close;   //- cur is the struct noted above

[...]

The struct dtor is automatically called upon exiting the scope, so your
scope(exit) here is redundant, and is the cause of the double free.


T



Sorry, but that wasn't the answer...which was trivial, when I saw it.  I
needed to change the close() routine to:
voidclose()
{  if(currentKey !is null)currentKey=null;
if(cursor is null)return;
tcbdbcurdel(cursor);
cursor  = null;
}

Apparently the library didn't null the cursor after it closed (deleted) it.


You're both right.

Your struct is presumably declared as a simple local variable, like this:

someFunction() {
  YOUR_STRUCT cur;
  ...
}

What we're saying is that cur's destructor is called automatically as 
soon as execution reaches the }, even if an exception is thrown or a 
break/continue/return/goto jumps out.


So when you write scope (exit) cur.close();, you're queueing the 
close() to happen under the same circumstances. This doesn't stop the 
destructor call happening. Your destructor calls close() too, so it gets 
called twice.


You should also know that the library you're using *can't* set 'cursor' 
to null for you, because you're in control of the memory location where 
'cursor' is stored (it's inside your struct), and when you pass it to 
tcbdbcurdel(), you're only passing a copy of the value. In order for it 
to set it to null for you, you would have pass a pointer to the value, 
by writing 'cursor'. (This is not strictly true for D or C++ functions 
since they can take 'references' which are implicit pointers, but you 
said it's a C library - and in any case, 'ref' parameters will usually 
be much more obviously 'ref' parameters than this one, if the API is 
well designed.)


So - setting cursor to null is a good safe fix, as it makes it safe to 
call close() more than once - but you also don't need the 'scope 
(exit)', as you can rely on the destructor being called.


(But further to that - you can only rely on the destructor being called 
if it's a struct (and not a pointer to one), or a scope class (a class 
with the 'scope' attribute). Normal classes will be destroyed eventually 
by the GC, but not at a well-defined time, and there's (probably?) no 
guarantee it'll be called before the program exits.)


I guess D isn't as simple as it wanted to be! But it is powerful :)


Re: static class

2013-02-20 Thread Ben Davis

On 18/02/2013 21:25, Michael wrote:

Yes, it's comes from C#.

So, there is no static for classes at module level. Good to have a msg
for it at compile-time.


import std.stdio;

public final abstract class Test
{
   static this() { writeln(in static ctor); }
   static :
   void foo() { writeln(in static method); }
}

void main()
{
   Test.foo();
}


public - adds a little bit of verbosity (ref
http://wiki.dlang.org/Access_specifiers_and_visibility). For now is noop.
final - adds a no inheritance.
abstract - disables non-static ctors.

right?


Technically 'abstract' doesn't disable the ctors; they would still be 
called by super() if you had a subclass (if you didn't use 'final'). 
What 'abstract' does is insist that all instances must be of some 
subtype, not of the class itself.


I'm sure you knew that and it's just a wording thing :)

Fun fact: in Java, it's an error to combine 'final' and 'abstract'.


Re: static class

2013-02-17 Thread Ben Davis

On 17/02/2013 22:25, Jonathan M Davis wrote:

On Sunday, February 17, 2013 23:00:19 Michael wrote:

That's not the meaning of static in that context.


As I understand a static class can't be instantiated.


I have no idea how you came to that conclusion.


In fairness, it is the natural guess you'd make if you haven't actively 
used nested instance classes and understood how the outer instance 
pointer is stored. We use Java at work (same mechanism as D), and hardly 
anyone actually knows to write 'static' when they create a nested class 
that they intend to be POD. :)



That's not what it means for a
class to be static at all. The only place that static has any effect on classes
is for nested classes. A static, nested class is like any other class except
that it's inside another class, which affects its path. e.g.

module b;

class C
{
 static class W
{
}
}

W is therefore b.C.W, whereas if it were not nested inside of C but next to it
within the same module, then it would be b.W.

However, non-static nested classes are associated with an instance of the
outer class, and therefore only one can exist per class instance.


That's not true, is it? You can make as many nested instances as you 
like. It's just that there must be some outer instance available at the 
time of construction (which can be a new one each time or the same one 
every time or anything in between).



However, it
also has access to that outer class instance through the property outer. e.g.

class C
{
 class R
 {
 void func()
 {
 //Sets the variable in the instance of
 //C that it's associated with.
 outer.i = 7;
 }
 }

 int i;
}


Is it possible to write someInstanceOfR.outer? I've occasionally wanted 
Java to have that feature, and ended up storing the 'outer' reference 
manually. Though this probably means I was writing bad code; I can't 
remember. :D


Re: For DLLs, what does export actually do?

2013-02-16 Thread Ben Davis

On 11/02/2013 16:06, Regan Heath wrote:

On Sun, 10 Feb 2013 12:36:38 -, Ben Davis ent...@cantab.net wrote:

DllMain is a weird one - it creates all sorts of linker errors if I
try it with extern(C) instead of extern(Windows) (which is different
from the other methods, which compile fine with extern(C) and then
crash at runtime).


extern(C) will change the mangling.. so in this case I guess the linker
is expecting DllMain but the mangling is incorrect.  I wonder if the
compiler detects the presence of DllMain and alters the linker line.
DMD has a command line option to output the linker command line, maybe
see if it changes with/without a DllMain in the code perhaps.


I think that's exactly what's going on. If it was only the mangling, I'd 
expect one error relating to that function, but instead I get at least 
10 errors relating to various functions I've never heard of. I don't 
think there's any particular need to test further.



Also it doesn't matter what name I export it by or whether I export it
at all. I'm getting the feeling this is what was implied by The
presence of DllMain() is recognized by the compiler. Good to know
anyway - I like to keep stuff clean :)


Yep, DllMain isn't a requirement, but if is present should be called by
the C runtime when the dll is loaded.  You can hook into process
start/stop and thread attach/detach with dll main.  It's good for thread
local storage initialisation - for example.


Yep, sounds about right - and it sounds like something that gets 
resolved in a special way when the DLL is linked. Certainly DllMain 
isn't appearing in my export table, yet I've established (by calling 
MessageBoxA from inside DllMain - that was brave of me, wasn't it? :P) 
that it is being called. :)


Re: How to interface to a C struct with volatile variables?

2013-02-16 Thread Ben Davis

On 16/02/2013 03:54, Charles Hixson wrote:

Does D have an equivalent to the C marking of volatile?

Currently I'm just going to try removing all variables from the struct,
as it's never declared in D or accessed from within D, and I just want
to avoid cast(void*)s, but I may need to access something like this
sometime in the future.


In your case, I think you can declare opaque structs in D:

struct S;   //Opaque
struct S { ... }//Not opaque

As for 'volatile', there's some info at 
http://dlang.org/deprecate.html#volatile about how it used to be 
available for marking statements as 'do not optimise field accesses'. 
The corrective action listed there is to use 'synchronized' instead. So 
probably your best bet is to use 'synchronized' blocks wherever you 
access the variables that you know are meant to be volatile.


Hope that helps :)


Re: How to interface to a C struct with volatile variables?

2013-02-16 Thread Ben Davis

On 16/02/2013 15:19, Jacob Carlborg wrote:

On 2013-02-16 15:13, Ben Davis wrote:

As for 'volatile', there's some info at
http://dlang.org/deprecate.html#volatile about how it used to be
available for marking statements as 'do not optimise field accesses'.
The corrective action listed there is to use 'synchronized' instead. So
probably your best bet is to use 'synchronized' blocks wherever you
access the variables that you know are meant to be volatile.

Hope that helps :)


If you're interfacing with C you should just remove the volatile
statement/keyword.

There is no volatile type modifier in D. To declare a C function that
uses volatile, just drop the keyword from the declaration.

http://dlang.org/interfaceToC.html


That's only telling you how to declare a C *function*, not a C struct 
(or global). While you'll probably get away with it in practice, I think 
dropping it from a struct is technically unsafe (and may break as a 
result of future compiler optimisation improvements) unless you back it 
up with the 'synchronized' strategy.


I was going to suggest __gshared, but for struct members it implies 
static, so it's not what you want. There doesn't seem to be a way to 
make a struct member 'volatile' for the purposes of interacting with C 
(which seems to be a gap in the C support).


Re: For DLLs, what does export actually do?

2013-02-10 Thread Ben Davis

On 10/02/2013 08:17, Benjamin Thaut wrote:

Am 10.02.2013 03:03, schrieb Ben Davis:


My functions are export extern (Windows) - I think they're global...?

For example:

export extern(Windows) LRESULT DriverProc(DWORD_PTR dwDriverId, HDRVR
hdrvr, UINT msg, LONG lParam1, LONG lParam2) nothrow { ... }


Do you have a copy of visual studio around? If so you can use
dumpbin /EXPORTS your.dll
 From a visual studio command shell to see the symbols the dll actually
exports. Just compare the version where you manually listed them in the
exports section with the version where you don't manually list exports.


Thanks, that helped expose what's going on.

With the def, I get lines like DriverProc = _DriverProc@20.
Without it, I get lines like _DriverProc@20 = _DriverProc@20.
So the difference is that the export is done under a slightly mangled 
name if I only mark it in the code, and I need to use the def file to 
specify the exact name to export by. I suppose this is only necessary 
for weird things like driver entry points, and not for normal exported 
functions.


A bit more Googling reveals that the @n is the number of bytes taken by 
arguments, and is part of the stdcall == extern(Windows) convention. So 
Windows is making me use stdcall and then making me throw that 
information away in the export table. But hey - it wouldn't be the worst 
thing I've encountered with the Windows API. (._.' :P)


DllMain is a weird one - it creates all sorts of linker errors if I try 
it with extern(C) instead of extern(Windows) (which is different from 
the other methods, which compile fine with extern(C) and then crash at 
runtime). Also it doesn't matter what name I export it by or whether I 
export it at all. I'm getting the feeling this is what was implied by 
The presence of DllMain() is recognized by the compiler. Good to know 
anyway - I like to keep stuff clean :)


Re: For DLLs, what does export actually do?

2013-02-10 Thread Ben Davis

On 10/02/2013 12:39, Benjamin Thaut wrote:

Am 10.02.2013 13:36, schrieb Ben Davis:

With the def, I get lines like DriverProc = _DriverProc@20.
Without it, I get lines like _DriverProc@20 = _DriverProc@20.


Then you did hit this 3 year old bug:
http://d.puremagic.com/issues/show_bug.cgi?id=3956


I don't think I did.

That bug applies to cases WITHOUT a .def file, and in that bug, the 
actual vs expected output is:


_DriverProc@mangledinsomeway (correct)
modMessage@mangledinsomeway (should be _modMessage@mangledinsomeway)
midMessage@mangledinsomeway (should be _midMessage@mangledinsomeway)

In my case, when I build without a .def file, I get:

_DriverProc@mangledinsomeway
_modMessage@mangledinsomeway
_midMessage@mangledinsomeway
not what I want, but correct as per the spec (I assume). Which would 
imply the bug was fixed at some point.


My example of DriverProc = (without the _) was WITH a .def file, AND 
is what I want - there is no bug as far as I'm aware.


For reference, when Andrej mentioned in earlier bug involving not having 
a .def, I thought of this one: 
http://www.digitalmars.com/d/archives/digitalmars/D/Windows_DLLs_and_TLS_177871.html


Hope it's clear now?

Ben :)


Re: For DLLs, what does export actually do?

2013-02-10 Thread Ben Davis

On 10/02/2013 14:11, Ben Davis wrote:

Which would imply the bug was fixed at some point.


...though of course it would need verifying with the example actually 
quoted in the bug, since there may be subtle differences. (Hopefully I'm 
just stating the obvious.)


Re: For DLLs, what does export actually do?

2013-02-09 Thread Ben Davis

On 09/02/2013 20:44, Andrej Mitrovic wrote:

On 2/9/13, Ben Davis ent...@cantab.net wrote:

Hi,

I'm working on a multimedia driver DLL, i.e. one that Windows loads on
behalf of any program that uses the Windows multimedia API.

I'm using a .def file with an EXPORTS section, and I've also got all the
relevant functions marked as 'export' in the code.


Export in code allows you to avoid listing exported functions in the
DEF file. However you should likely still use the DEF file even if it
lacks a list, as I recall there's a bug related to not using DEF files
(I can't find the issue right now).


(Oops, silly Thunderbird)

I know which issue you mean, because I came across it earlier. It's 
something about needing EXETYPE NT and SUBSYSTEM WINDOWS or else 
something bad happens with thread-local storage. I don't think it had 
anything to do with exports.


What you're telling me (about the purpose of export in code) is what I 
assumed was the intention, but the fact is it's not behaving that way. 
If I mark the functions as export in the code, but remove the EXPORTS 
section from the .def file (but keep the rest of the .def file), then 
the DLL doesn't work, which suggests that the export table did not 
contain those functions.


Perhaps the exports in the code only apply if the .def is entirely 
missing? Is that the desired behaviour? (I won't be trying that, as I 
know it would break in other ways then.)


Ben :)


Re: For DLLs, what does export actually do?

2013-02-09 Thread Ben Davis

On 09/02/2013 20:39, Benjamin Thaut wrote:

Am 09.02.2013 21:35, schrieb Ben Davis:

Hi,

I'm working on a multimedia driver DLL, i.e. one that Windows loads on
behalf of any program that uses the Windows multimedia API.

I'm using a .def file with an EXPORTS section, and I've also got all the
relevant functions marked as 'export' in the code.

What I'm finding is, if I remove the 'export' attribute but keep the
EXPORTS section, it all still works; but if I keep the 'export'
attribute and remove the EXPORTS section, then it doesn't work.

Just wondering why this is, and whether the 'export' attribute is
actually programmed to do anything at the moment :)

Thanks,

Ben :)


Yes it is, but its only working properly for global functions. It works
partially for classes and not at all for all remaining cases. The export
attribute is currently only usefull if you want to do a C-Style
interface for your Dll.


My functions are export extern (Windows) - I think they're global...?

For example:

export extern(Windows) LRESULT DriverProc(DWORD_PTR dwDriverId, HDRVR 
hdrvr, UINT msg, LONG lParam1, LONG lParam2) nothrow { ... }


Automatic return type covariance for functions that return this?

2012-09-15 Thread Ben Davis

Hi,

Is it possible in D to achieve this effect:

class Super {
  typeof(this) doStuff() { ...; return this; }
}

class Sub : Super {
  //doStuff is NOT explicitly overridden here
}

Sub x = (new Sub()).doStuff();

The last line doesn't compile because doStuff() returns Super. Is there 
a way to make it return Sub without having to explicitly override the 
function?


Thanks in advance,

Ben :)


Re: Automatic return type covariance for functions that return this?

2012-09-15 Thread Ben Davis

Never mind, I found the answer in the 'templates' page of the spec:

class Super {
   T doStuff(this T)() { ...; return cast(T)this; }
}

Sub x = (new Sub()).doStuff();

It seems a bit of a shame that I need the cast, but it's a small thing :)

On 15/09/2012 22:53, Ben Davis wrote:

Hi,

Is it possible in D to achieve this effect:

class Super {
   typeof(this) doStuff() { ...; return this; }
}

class Sub : Super {
   //doStuff is NOT explicitly overridden here
}

Sub x = (new Sub()).doStuff();

The last line doesn't compile because doStuff() returns Super. Is there
a way to make it return Sub without having to explicitly override the
function?

Thanks in advance,

Ben :)




Re: Const lazy arguments?

2012-01-11 Thread Ben Davis
If you had a const lazy SomeClass con and a lazy SomeClass mut, you 
could write mut.x=y but not con.x=y. I think.


On 11/01/2012 04:46, bearophile wrote:

I ask here first before submitting about this to Bugzilla.

If lazy arguments can't be lvalues:


void foo(lazy int x) {
 x = x;
}
void main() {}

==
test.d(2): Error: lazy variables cannot be lvalues


What's the point of accepting const lazy arguments?

void foo(const lazy int x) {}
void main() {}

Bye,
bearophile




Ref local variables?

2012-01-08 Thread Ben Davis

Hi,

Is there a reason 'ref' is disallowed for local variables? I want to 
write something like:


MapTile[] map;  // It's a struct

ref MapTile tile=map[y*w+x];
tile.id=something;
tile.isWall=true;

My actual case is more complicated, so inlining the expression 
everywhere would be messy. I can't use 'with' because I sometimes pass 
'tile' to a function (which also takes it as a ref). I don't want to 
make it a class since the array is quite big and that would be a lot of 
extra overhead. For now I'm using pointers, but this is forcing me to 
insert  or * operators sometimes, and it also reduces the temptation to 
use 'ref' in the places where it IS allowed, since it's inconsistent.


I hope it's not a stupid question - it's my first one - but I couldn't 
find an answer anywhere. I like most of what I've seen of D so far, and 
I'm very glad to be able to leave C and C++ (mostly) behind!


Thanks,

Ben :)


Re: Ref local variables?

2012-01-08 Thread Ben Davis

I also meant to say: 80x25? Epic :D

On 08/01/2012 20:25, Ben Davis wrote:

There are two things going on in your example:

1. Use of 'auto' where I'm currently having to write 'MapTile*' and
wanted to write 'ref MapTile'. It will infer 'MapTile*'. Or, if you
forget the , then it will infer 'MapTile' and do the copy that I want
to avoid. So it might be slightly more error-prone this way.

2. Use of a template function, allowing f() to take any type, not just
MapTile. Interestingly you're passing MapTile*, AND the parameter is
ref, so f() could change the pointer itself for the caller if it wanted
to! Also, if you called f() elsewhere with just a MapTile, you'd have
two copies if the function kicking around. So it saves us having to
write the *, but at the expense of some messiness. (Also prevents a lot
of the compile-time checks for f() from happening until f() is used.)

At least that's assuming D templates are like C++ ones. I haven't read
up on D templates yet. :)

So unfortunately, neither solution really solves the problem.

I suspect 'ref' for local variables could be added, and hasn't because
it didn't figure in the specific use cases that someone had in mind when
implementing it for parameters and 'foreach' variables. But it's also
possible that (unlike in Java) local variables can do stuff that
parameters can't (which I don't know about), which makes it impossible
to allow 'ref' ones without invalidating a compile-time check or
something. Hence why I was asking. :)

Anyway, I hope I've been able to help a bit with your own D adventure :)

Ben :)

On 08/01/2012 19:27, simendsjo wrote:

I got something working, but only when using templates. Take the
following with a grain of salt as I'm a newbie myself.

struct MapTile {
string id;
}

enum w = 80, h = 25;
MapTile[w*h] map;

ref MapTile getTile(int x, int y) {
return map[y*w+x];
}

void f(T)(ref T tile) {
tile.id = f();
}

void g(ref MapTile tile) {
tile.id = g();
}

void main() {
// You can use auto ref return to set values directly
getTile(10,10).id = a;
assert(getTile(10,10).id == a);

// And using templated ref arguments, you can pass by reference
// note that I need to take the reference even when
// using auto ref return
auto tile = getTile(1,1);
f(tile);
assert(tile.id == f());

// But you'll need a dereference if not using a template
g(*tile);
assert(tile.id == g());

assert(getTile(1,1).id == g());
}







Re: Ref local variables?

2012-01-08 Thread Ben Davis

There are two things going on in your example:

1. Use of 'auto' where I'm currently having to write 'MapTile*' and 
wanted to write 'ref MapTile'. It will infer 'MapTile*'. Or, if you 
forget the , then it will infer 'MapTile' and do the copy that I want 
to avoid. So it might be slightly more error-prone this way.


2. Use of a template function, allowing f() to take any type, not just 
MapTile. Interestingly you're passing MapTile*, AND the parameter is 
ref, so f() could change the pointer itself for the caller if it wanted 
to! Also, if you called f() elsewhere with just a MapTile, you'd have 
two copies if the function kicking around. So it saves us having to 
write the *, but at the expense of some messiness. (Also prevents a lot 
of the compile-time checks for f() from happening until f() is used.)


At least that's assuming D templates are like C++ ones. I haven't read 
up on D templates yet. :)


So unfortunately, neither solution really solves the problem.

I suspect 'ref' for local variables could be added, and hasn't because 
it didn't figure in the specific use cases that someone had in mind when 
implementing it for parameters and 'foreach' variables. But it's also 
possible that (unlike in Java) local variables can do stuff that 
parameters can't (which I don't know about), which makes it impossible 
to allow 'ref' ones without invalidating a compile-time check or 
something. Hence why I was asking. :)


Anyway, I hope I've been able to help a bit with your own D adventure :)

Ben :)

On 08/01/2012 19:27, simendsjo wrote:

I got something working, but only when using templates. Take the
following with a grain of salt as I'm a newbie myself.

struct MapTile {
string id;
}

enum w = 80, h = 25;
MapTile[w*h] map;

ref MapTile getTile(int x, int y) {
return map[y*w+x];
}

void f(T)(ref T tile) {
tile.id = f();
}

void g(ref MapTile tile) {
tile.id = g();
}

void main() {
// You can use auto ref return to set values directly
getTile(10,10).id = a;
assert(getTile(10,10).id == a);

// And using templated ref arguments, you can pass by reference
// note that I need to take the reference even when
// using auto ref return
auto tile = getTile(1,1);
f(tile);
assert(tile.id == f());

// But you'll need a dereference if not using a template
g(*tile);
assert(tile.id == g());

assert(getTile(1,1).id == g());
}