Re: Interfacing with C - calling member function of D struct from C?
On Sunday, 25 June 2017 at 02:05:35 UTC, unleashy wrote: How would I call `addToBar` from C code? You don't. Instead write it like: struct Foo { int bar; } extern(C) void addToBar(Foo* foo, int what) { foo.bar += what; } Then define it in C the same way and you call it the normal way from C. But from D, you can UFCS call it: Foo* foo = new Foo(); foo.addToBar(5); // cool though I'd prolly just call it from D the same way you do from C too.
Interfacing with C - calling member function of D struct from C?
Hello! If I have a D struct like: struct Foo { int bar; void addToBar(int what) { bar += what; } } How would I call `addToBar` from C code? Would I need to put the `addToBar` function outside of the struct and mark it as `extern (C)` and in normal D code take advantage of UFCS or is there some magic C incantation? I've scoured the forums and other places for anything about this but couldn't find any information whatsoever... so yeah. (or my Google-fu is terrible) Thanks!
Re: casting to structure
On Saturday, 24 June 2017 at 21:41:22 UTC, Moritz Maxeiner wrote: Hi, unfortunately not: - Operator overloading is supported via member functions only [1]. - Corollary: You cannot overload operators for builtin types (i.e. where the cast gets rewritten to `e.opOverloaded` where `e` is a builtin type) - opCast needs to be defined for the type that you are casting from [2], not the one you are casting to => You cannot overload opCast for casting from builtin types [...] You cannot. As any such cast operation would have to create a new A object, anyway (and would as such be a wrapper around a (possibly default) constructor), I suggest using elaborate constructors: Thank you for your detailed explanation! Word of warning, though: What you're doing is highly unsafe. I guess it is unsafe, but core.sys.windows module works this way. That *is* how the Windows C API works AFAIK. I have no choice except for using it as it is. Define a struct for HWND as shown above for A and use constructors. Add an `alias this` to the wrapped pointer value. That was the first thing I did. And it is led me to my question. Thank you!
Re: casting to structure
On Saturday, 24 June 2017 at 21:11:13 UTC, Igor Shirkalin wrote: Is it possible without such a constructor? No. Also, the above works because of the following [1]: Casting a value v to a struct S, when value is not a struct of the same type, is equivalent to: `S(v)` [1] https://dlang.org/spec/expression.html#CastExpression
Re: casting to structure
On Saturday, 24 June 2017 at 20:43:48 UTC, Igor Shirkalin wrote: I'm in trouble with opCast function. Is it possible to cast some (integral) type to user defined structure? Hi, unfortunately not: - Operator overloading is supported via member functions only [1]. - Corollary: You cannot overload operators for builtin types (i.e. where the cast gets rewritten to `e.opOverloaded` where `e` is a builtin type) - opCast needs to be defined for the type that you are casting from [2], not the one you are casting to => You cannot overload opCast for casting from builtin types [...] How can we define opCast operator to make the following expression working properly? auto a = cast(A) 12; You cannot. As any such cast operation would have to create a new A object, anyway (and would as such be a wrapper around a (possibly default) constructor), I suggest using elaborate constructors: --- struct A { void* data; this(int data) { this.data = cast(void*) data; } } ... auto a = A(12); --- The task arised from core.sys.windows module. This module defines a lot of windows specific types based on HANDLE: these are HWND, HDC, HBITMAP, etc. The problem is that all these types are identical, and it is too bad. Why is this a problem? That *is* how the Windows C API works AFAIK. Typesafety would require a higher abstraction level than the Windows C API functions provide, anyway. When I redefine these types like: alias Typedef!(void*) HDC; I have another problem: HWND_MESSAGE = cast(HWND) -3; // Error: cannot cast expression -3 of type int to Typedef!(void*, null, null) You have explicitly asked for those two types to be different from each other [3]; that means they are also *not* implicitly convertible to each other and thus you also cannot cast from one to the other without defining an opCast (which you can't in this case, since the source type is a builtin type). So, is there any solution to this? Define a struct for HWND as shown above for A and use constructors. Add an `alias this` to the wrapped pointer value. Word of warning, though: What you're doing is highly unsafe. [1] https://dlang.org/spec/operatoroverloading.html [2] https://dlang.org/spec/operatoroverloading.html#cast [3] https://dlang.org/phobos/std_typecons.html#.Typedef
Re: casting to structure
On Saturday, 24 June 2017 at 20:43:48 UTC, Igor Shirkalin wrote: struct A { void * data; // void * type is just for example // no matter what is here } I know that if I add constructor this(int) struct A { void * p; this(int k) { p = cast(void*)k; } } auto a = cast(A) 23; // it works Is it possible without such a constructor?
casting to structure
Hello! I'm in trouble with opCast function. Is it possible to cast some (integral) type to user defined structure? We have a structure: struct A { void * data; // void * type is just for example // no matter what is here } How can we define opCast operator to make the following expression working properly? auto a = cast(A) 12; The task arised from core.sys.windows module. This module defines a lot of windows specific types based on HANDLE: these are HWND, HDC, HBITMAP, etc. The problem is that all these types are identical, and it is too bad. When I redefine these types like: alias Typedef!(void*) HDC; I have another problem: HWND_MESSAGE = cast(HWND) -3; // Error: cannot cast expression -3 of type int to Typedef!(void*, null, null) So, is there any solution to this?
Re: What's the fastest way to check if a slice points to static data
On Saturday, 24 June 2017 at 18:46:06 UTC, ketmar wrote: Petar Kirov [ZombineDev] wrote: Oh, I should have mentioned that I don't expect anything but ugly platform-specific hacks possibly involving the object file format ;) Just enough of them to claim that the solution is somewhat cross-platform :D i guess you can loot at how TSL scanning is done in druntime (at least on GNU/Linux). it does some parsing of internal structures of loaded ELF. i guess you can parse section part of the loaded ELF too, to find out r/o sections and their address ranges. that's the stuff :P
Re: What's the fastest way to check if a slice points to static data
Petar Kirov [ZombineDev] wrote: Oh, I should have mentioned that I don't expect anything but ugly platform-specific hacks possibly involving the object file format ;) Just enough of them to claim that the solution is somewhat cross-platform :D i guess you can loot at how TSL scanning is done in druntime (at least on GNU/Linux). it does some parsing of internal structures of loaded ELF. i guess you can parse section part of the loaded ELF too, to find out r/o sections and their address ranges.
Re: Targetting the 8051
On Sat, 2017-06-24 at 18:04 +, FoxyBrown via Digitalmars-d-learn wrote: > 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). Sorry but this is an ill-defined wish list. 8051 processors about in the world just as they did 15 years ago. They are however very low level things. Most people use assembler or specially extended C – to deal with the 8-bit structure and the bit-addressable values some 8051 variants have. Trying to work with a 32-bit or 64-bit focused language on an 8-bit target is never going to work particularly well. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Re: What's the fastest way to check if a slice points to static data
On Saturday, 24 June 2017 at 18:05:55 UTC, ketmar wrote: Petar Kirov [ZombineDev] wrote: *** But in any case, the null-terminated string was just an example application. I'm interested in a fast way to determine the "storage class" of the memory a slice or a pointer point to. I'm expecting some magic along the lines of checking the range of addresses that the rodata section resides in memory. Similar to how some allocators or the GC know if they own a range of memory. Any ideas on that? *** the only query you can do is GC query (see `core.memory.CG` namespace, `addrOf()` API, for example). it will tell you if something was allocated with D GC or not. yet it is not guaranteed to be fast (althru it is usually "fast enough"). I'm not interested in asking the GC specifically, but I have looked at its implementation and I know that it keeps such information around: https://github.com/dlang/druntime/blob/v2.074.1/src/gc/impl/conservative/gc.d#L843 i think this is all what you can get without resorting to ugly platform-specific hacks (that will inevitably break ;-). Oh, I should have mentioned that I don't expect anything but ugly platform-specific hacks possibly involving the object file format ;) Just enough of them to claim that the solution is somewhat cross-platform :D
Re: What's the fastest way to check if a slice points to static data
Petar Kirov [ZombineDev] wrote: *** But in any case, the null-terminated string was just an example application. I'm interested in a fast way to determine the "storage class" of the memory a slice or a pointer point to. I'm expecting some magic along the lines of checking the range of addresses that the rodata section resides in memory. Similar to how some allocators or the GC know if they own a range of memory. Any ideas on that? *** the only query you can do is GC query (see `core.memory.CG` namespace, `addrOf()` API, for example). it will tell you if something was allocated with D GC or not. yet it is not guaranteed to be fast (althru it is usually "fast enough"). i think this is all what you can get without resorting to ugly platform-specific hacks (that will inevitably break ;-).
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).
Re: What's the fastest way to check if a slice points to static data
On Saturday, 24 June 2017 at 14:18:33 UTC, ketmar wrote: with the edge case when something like the code i posted below managed to make `a` perfectly aligned with r/o area, and you got segfault by accising out-of-bounds byte. BTW, are you sure? AFAIU, it doesn't matter if the CTFE engine returns a non-null-terminated string expression, since the backend or the glue layer would write it to the object file as if it was a null-terminated string. immutable ubyte[2] a = [65,66]; enum string s = cast(string)a; immutable ubyte[2] b = [67,68]; // just to show you that there is no zero void main () { assert(s[$-1] == 0); } Thanks, I haven't considered immutable statically allocated fixed-size arrays of chars. Specifically, while mutable fixed-size arrays of both character and non-character type are common, I don't think immutable fixed-size char arrays are much used compared to string literals and ctfe-derived strings. I'm tempted to write in the documentation of my hypothetical fastStringZ function that passing anything, but something originating from a slice is UB, though I'm aware how under-specified and hand-wavy this sounds. On Saturday, 24 June 2017 at 14:21:23 UTC, ketmar wrote: ketmar wrote: p.s.: btw, druntime tries to avoid that edge case by not checking for trailing out-of-bounds zero if string ends exactly on dword boundary. it will miss some strings this way, but otherwise it is perfectly safe. oops. not druntime, phobos, in `std.string.toStringz()`. Thanks, for some reason I assumed that toStringz always conservatively copies the string, without even checking the code. It looks like the more aggressive optimization was at some point removed which is visible in this revision: http://www.dsource.org/projects/phobos/changeset/101#file15 and later Andrei reintroduced it with the more conservative heuristic: https://github.com/dlang/phobos/commit/460c844b4fb9b96833871c111dd529d22129ab7c, but I didn't manage to find any discussion about it. *** But in any case, the null-terminated string was just an example application. I'm interested in a fast way to determine the "storage class" of the memory a slice or a pointer point to. I'm expecting some magic along the lines of checking the range of addresses that the rodata section resides in memory. Similar to how some allocators or the GC know if they own a range of memory. Any ideas on that? ***
Re: Help me escape optional parens hell
On Saturday, 24 June 2017 at 08:08:33 UTC, ketmar wrote: Meta wrote: So I have no clue what I'm doing wrong. This is driving me insane. h. known $#^#$@^@%. enum SymName = ().stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there. It's dirty but I guess I'll have to go with this hack for the time being. Also, I filed a bug: https://issues.dlang.org/show_bug.cgi?id=17546
Re: Are padding bits always zero?
On 6/24/17 10:32 AM, Honey wrote: On Saturday, 24 June 2017 at 12:41:47 UTC, Steven Schveighoffer wrote: Any padding bits between fields should be 0 as long as the struct is initialized (i.e. as long as you don't do Struct s = void). Padding bits after the fields I assume would be 0, but I don't know if this is defined. It's possible the compiler doesn't consider those bits to be part of the struct, and just there for alignment. There is no spec for this, but I know that when the compiler has to fill gaps with something it chooses 0. Thanks. Your answer has generated more questions. ;-) Let's say, I have a struct S of size n with m bits of padding at the end. How can I find m? Is it possible to provide a facility Pad such that for any struct T, Pad!T is a struct that mimics T but contains explicit instead of implicit padding? E.g. struct Foo { ubyte b; double d; int i; } struct Pad!Foo { ubyte b; ubyte[7] __padding_0; double d; int i; ubyte[4] __padding_1; } Of course it's possible. Best thing I can think of is using offsetof and sizeof: string generatePad(T)() { string result = ""; size_t lastIndex = 0; foreach(x; T.tupleof) { // not sure about offsetof working like this, you may need to do // tupleof with index auto padSpace = x.offsetof - lastIndex; if(padSpace > 0) result ~= "ubyte[" ~ padSpace ~ "] __padding__" ~ padIndex ~ ";"; result ~= typeof(x).stringof ~ " " ~ x.stringof ~ ";"; lastIndex = x.offsetof + x.sizeof; } return result; } This needs a bit of work, but you get the idea. I'm not sure all the properties work correctly there. Then you mixin the result of that function to get your members. Adding the ending padding would involve comparing lastIndex to the sizeof T. -Steve
Re: Are padding bits always zero?
On Saturday, 24 June 2017 at 14:03:16 UTC, Adam D. Ruppe wrote: On Saturday, 24 June 2017 at 12:41:47 UTC, Steven Schveighoffer wrote: There is no spec for this, but I know that when the compiler has to fill gaps with something it chooses 0. I'm almost certain there at least used to be a spec for this, because I remember citing a link to someone who then complained that this zero requirement hurt optimization of void members. On the other hand though, the zero padding requirement does simplify equality to being memcmp. The only hint I could find is this statement from Walter: http://forum.dlang.org/post/hn11oh$1usk$1...@digitalmars.com
Re: Are padding bits always zero?
On Saturday, 24 June 2017 at 14:03:16 UTC, Adam D. Ruppe wrote: On the other hand though, the zero padding requirement does simplify equality to being memcmp. That's the reason for my question.
Re: Are padding bits always zero?
On Saturday, 24 June 2017 at 12:41:47 UTC, Steven Schveighoffer wrote: Any padding bits between fields should be 0 as long as the struct is initialized (i.e. as long as you don't do Struct s = void). Padding bits after the fields I assume would be 0, but I don't know if this is defined. It's possible the compiler doesn't consider those bits to be part of the struct, and just there for alignment. There is no spec for this, but I know that when the compiler has to fill gaps with something it chooses 0. Thanks. Your answer has generated more questions. ;-) Let's say, I have a struct S of size n with m bits of padding at the end. How can I find m? Is it possible to provide a facility Pad such that for any struct T, Pad!T is a struct that mimics T but contains explicit instead of implicit padding? E.g. struct Foo { ubyte b; double d; int i; } struct Pad!Foo { ubyte b; ubyte[7] __padding_0; double d; int i; ubyte[4] __padding_1; }
Re: What's the fastest way to check if a slice points to static data
ketmar wrote: p.s.: btw, druntime tries to avoid that edge case by not checking for trailing out-of-bounds zero if string ends exactly on dword boundary. it will miss some strings this way, but otherwise it is perfectly safe. oops. not druntime, phobos, in `std.string.toStringz()`.
Re: What's the fastest way to check if a slice points to static data
p.s.: btw, druntime tries to avoid that edge case by not checking for trailing out-of-bounds zero if string ends exactly on dword boundary. it will miss some strings this way, but otherwise it is perfectly safe.
Re: What's the fastest way to check if a slice points to static data
Petar Kirov [ZombineDev] wrote: Please note that not all static immutable strings have to be null terminated. It is possible to generate a string at ctfe which may appear the same as string literal, but does not have the \0 at the end. But in that case, the check `s.ptr[s.length] == 0` in fastStringZ would do the trick, right? with the edge case when something like the code i posted below managed to make `a` perfectly aligned with r/o area, and you got segfault by accising out-of-bounds byte. BTW, are you sure? AFAIU, it doesn't matter if the CTFE engine returns a non-null-terminated string expression, since the backend or the glue layer would write it to the object file as if it was a null-terminated string. immutable ubyte[2] a = [65,66]; enum string s = cast(string)a; immutable ubyte[2] b = [67,68]; // just to show you that there is no zero void main () { assert(s[$-1] == 0); }
Re: What's the fastest way to check if a slice points to static data
On Saturday, 24 June 2017 at 13:11:02 UTC, Stefan Koch wrote: On Saturday, 24 June 2017 at 12:22:54 UTC, Petar Kirov [ZombineDev] wrote: [ ... ] /** * Returns: * A pointer to a null-terminated string in O(1) time, * (with regards to the length of the string and the required * memory, if any) or `null` if * the time constraint * can't be met. */ immutable(T)* fastStringZ(T)(return immutable(T)[] s) @trusted if (isSomeChar!T) { if (isStaticallyAllocated(s) && s.ptr[s.length] == 0) return s.ptr; else return null; } --- (Without `isStaticallyAllocated`, `fastStringZ` may *appear* to work but if you pass the pointer to e.g. a C library and that library keeps it after the call has completed, good luck tracking memory corruption if the slice was pointing to automatic/dynamic memory - e.g. static array buffer on the stack or GC / RC * heap allocation. * malloc or custom allocator + smart pointer wrapper) Please note that not all static immutable strings have to be null terminated. It is possible to generate a string at ctfe which may appear the same as string literal, but does not have the \0 at the end. But in that case, the check `s.ptr[s.length] == 0` in fastStringZ would do the trick, right? BTW, are you sure? AFAIU, it doesn't matter if the CTFE engine returns a non-null-terminated string expression, since the backend or the glue layer would write it to the object file as if it was a null-terminated string. But you're right if you mean that this trick won't work in CTFE, since the `s.ptr[s.length] == 0` trick rightfully is disallowed. --- void main() { static immutable str = generateString(); pragma (msg, str, " is null-terminated at CT: ", str.isNullTerminated()); import std.stdio; writeln(str, " is null-terminated at RT: ", str.isNullTerminated()); } string generateString() { string res; foreach (i; 0 .. 26) res ~= 'a' + i; return res; } import std.traits : isSomeChar; bool isNullTerminated(T)(scope const T[] str) if (isSomeChar!T) { if (!__ctfe) return str.ptr[str.length] == 0; else return false; } --- Compilation output: abcdefghijklmnopqrstuvwxyz is null-terminated at CT: false Application output: abcdefghijklmnopqrstuvwxyz is null-terminated at RT: true
Re: Converting a ubyte[] to a struct with respect to endianness?
On Saturday, 24 June 2017 at 02:52:23 UTC, Felix wrote: I'm trying to read in just the first part of a .png file to peek at it's width and height without loading in the whole file. I'm using FreeImage for reading the whole file but since it doesn't have a function to let me peek at the image size before loading it all in I'm rolling my own. I've gotten as a far as reading in the first 16 bytes which includes an 8 byte signature, then the length and type of the first chunk: struct Header { ubyte[8] signature; uint length; char[4] type; } union Un { Header h; ubyte[16] u; } auto f = File(path, "r"); foreach (ubyte[] buffer; f.byChunk(16)){ Un fff; fff.u = buffer[0..16]; writeln(fff.h); break; } It prints out: Header([137, 80, 78, 71, 13, 10, 26, 10], 218103808, "IHDR") The signature is correct, the type is correct, but the value I get for length should be 13, not 218103808. So I'm guessing my ubytes are in the wrong order in the uint... how should I put them around the correct way so that my code won't break on another machine with different endianness? I would advise a look at sqlite.d https://github.com/UplinkCoder/sqlite-d which solves the same problem albeit for sqlite database files and for png. But it provides the means of simply putting a BigEndian!uint into your struct and have conversion on stuff be automatically handled.
Re: Are padding bits always zero?
On Saturday, 24 June 2017 at 12:41:47 UTC, Steven Schveighoffer wrote: There is no spec for this, but I know that when the compiler has to fill gaps with something it chooses 0. I'm almost certain there at least used to be a spec for this, because I remember citing a link to someone who then complained that this zero requirement hurt optimization of void members. On the other hand though, the zero padding requirement does simplify equality to being memcmp. I can't find the reference now. Perhaps I'm looking in the wrong place... or perhaps that optimization complaint actually got the requirement removed from the spec. I don't know. (I find search of most D stuff to be fruitless and heavily rely on my old brain memory to index these things, but while my memory is pretty good, it isn't flawless.)
Re: What's the fastest way to check if a slice points to static data
On Saturday, 24 June 2017 at 12:22:54 UTC, Petar Kirov [ZombineDev] wrote: [ ... ] /** * Returns: * A pointer to a null-terminated string in O(1) time, * (with regards to the length of the string and the required * memory, if any) or `null` if * the time constraint * can't be met. */ immutable(T)* fastStringZ(T)(return immutable(T)[] s) @trusted if (isSomeChar!T) { if (isStaticallyAllocated(s) && s.ptr[s.length] == 0) return s.ptr; else return null; } --- (Without `isStaticallyAllocated`, `fastStringZ` may *appear* to work but if you pass the pointer to e.g. a C library and that library keeps it after the call has completed, good luck tracking memory corruption if the slice was pointing to automatic/dynamic memory - e.g. static array buffer on the stack or GC / RC * heap allocation. * malloc or custom allocator + smart pointer wrapper) Please note that not all static immutable strings have to be null terminated. It is possible to generate a string at ctfe which may appear the same as string literal, but does not have the \0 at the end.
Re: Are padding bits always zero?
On 6/24/17 4:44 AM, Honey wrote: Hi everyone! Are there any guarantees about the values of padding bits in structs? Thanks, Honey Any padding bits between fields should be 0 as long as the struct is initialized (i.e. as long as you don't do Struct s = void). Padding bits after the fields I assume would be 0, but I don't know if this is defined. It's possible the compiler doesn't consider those bits to be part of the struct, and just there for alignment. There is no spec for this, but I know that when the compiler has to fill gaps with something it chooses 0. -Steve
Re: Converting a ubyte[] to a struct with respect to endianness?
On 6/24/17 1:18 AM, H. S. Teoh via Digitalmars-d-learn wrote: On Fri, Jun 23, 2017 at 10:10:22PM -0700, Ali Çehreli via Digitalmars-d-learn wrote: On 06/23/2017 09:26 PM, Felix wrote: That works, thanks! I've just tried this, which seems cleaner: import std.stdio; import std.system; import std.bitmanip; void ensureBigEndian(T)(ref T value) { if (endian == Endian.littleEndian) { value = *cast(T*)nativeToBigEndian(value).ptr; } This is wrong, you should be detecting the endianness of the input and use {big,little}EndianToNative instead. For example, if the input is big endian, you should use bigEndianToNative. Internally, if native is already big endian, it will do nothing; otherwise it will swap the endianness. This way you don't have to check the current machine's endianness yourself; you can just recompile on a machine of different endianness and it will Just Work. I would also point out that there are pre-defined versions for endianness: version(BigEndian) and version(LittleEndian). This makes static checking a lot easier when you are writing your own code that deals with endiannness. For byte-swapping one field, I would use the standard tools as H.S. has advised. -Steve
What's the fastest way to check if a slice points to static data
I need a fast and hopefully relatively cross-platform (ELF, OMF, COFF and MachO) way of checking if a slice points to data in the read-only section of the binary, i.e. it's pointing to a statically-allocated piece of memory. Of course a simple solution using meta programming would be: --- enum isStaticallyAllocated(alias var) = __traits(compiles, { // ensures that the value is known at compile-time enum value = var; // ensures that it's not a manifest constant and that it's // actually going to be part of the binary (modulo linker // optimizations like gc-sections). static immutable addr = }); enum x = 3; static immutable y = 4; immutable z = 5; int w = 6; void main() { enum localX = 3; static immutable localY = 4; immutable localZ = 5; int localW = 6; pragma (msg, isStaticallyAllocated!x); // false pragma (msg, isStaticallyAllocated!y); // true pragma (msg, isStaticallyAllocated!z); // true pragma (msg, isStaticallyAllocated!w); // false pragma (msg, isStaticallyAllocated!localX); // false pragma (msg, isStaticallyAllocated!localY); // true pragma (msg, isStaticallyAllocated!localZ); // false pragma (msg, isStaticallyAllocated!localW); // false } --- However, that doesn't work when all you have is a slice as a run-time argument to a function. Additionally, if the the slice was constructed from a string literal, it should possible to recover a pointer to the zero-terminated string. Or in pseudo-code: --- void main() { import core.stdc.stdio : printf; auto p = "test".fastStringZ; p || assert(0, "Something is terribly wrong!"); printf("%s\n", p); } import std.traits : isSomeChar; // Does the magic bool isStaticallyAllocated(in scope void[] slice) { // XXX_XXX Fix me return true; } /** * Returns: * A pointer to a null-terminated string in O(1) time, * (with regards to the length of the string and the required * memory, if any) or `null` if * the time constraint * can't be met. */ immutable(T)* fastStringZ(T)(return immutable(T)[] s) @trusted if (isSomeChar!T) { if (isStaticallyAllocated(s) && s.ptr[s.length] == 0) return s.ptr; else return null; } --- (Without `isStaticallyAllocated`, `fastStringZ` may *appear* to work but if you pass the pointer to e.g. a C library and that library keeps it after the call has completed, good luck tracking memory corruption if the slice was pointing to automatic/dynamic memory - e.g. static array buffer on the stack or GC / RC * heap allocation. * malloc or custom allocator + smart pointer wrapper)
Re: Help me escape optional parens hell
On 6/24/17 3:53 AM, Meta wrote: The code: alias Response = Nullable!(string, "empty response (error)"); Response processMessage(string commandModule)(string message, bool isCommand) { import std.meta; import std.string; import std.traits; import command_uda; mixin("import " ~ commandModule ~ ';'); bool foundCommandMatch = false; foreach(symbol; getSymbolsByUDA!(mixin(commandModule), Command)) { enum commandUDA = getUDAs!(symbol, Command)[0]; auto commandPhrase = commandUDA.phrase == "" ? symbol.stringof : commandUDA.phrase; //Error: function is not callable using argument types () auto commandPhrasePattern = regex(`^%s\s`.format(commandPhrase)); if (message.matchFirst(commandPhrasePattern) && !foundCommandMatch) { version(responseDebug) writeln("Matched command ", symbol.stringof, " with phrase '", commandPhrase, "'\n"); //Same issue return Response(symbol(message.strip())); } } return Response.init; } I've been banging my head against this and cannot figure out why `symbol.stringof` is being called instead of getting a string of the symbol. I tried to create a reduced test case but it works fine: import std.stdio; import std.traits; enum Attr; @Attr string test1() { return __FUNCTION__; } @Attr string test2() { return __FUNCTION__; } void process() { foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr)) { writeln("The result of calling ", symbol.stringof, " is ", symbol()); } } void main() { process(); } So I have no clue what I'm doing wrong. This is driving me insane. I know what you are doing wrong in your reduced case. Try this instead: @Attr string test1(int) { return __FUNCTION__; } @Attr string test2(int) { return __FUNCTION__; } void process() { foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr)) { writeln("The result of calling ", symbol.stringof, " is ", symbol(1)); } } The reason your version "works" is because your functions actually are callable with no args! I tried many things including: enum symbolname = symbol.stringof; enum symbolname = (symbol).stringof; pragma(msg, symbol.stringof); Nothing works. If this isn't already a bug, you should file it. Aside from ketmar's workaround, I can't think of one. It's interesting that the ability to call without parentheses is what causes the error, yet when you *can* call without parentheses, it doesn't actually do so (symbol.stringof prints the name of the symbol). This seems very obviously to be a bug. -Steve
Re: More optional parens concerns
On Saturday, June 24, 2017 9:56:55 AM MDT Russel Winder via Digitalmars-d- learn wrote: > I note that: > > x.map!(…).array.sort > > is not valid, you have to have the parentheses on sort: > > x.map!(…).array.sort() > > Why? Because the built-in sort for arrays has been deprecated but not yet removed. So, for now, calling sort on an array without parens calls the built-in sort. Once the built-in sort has been removed, then this problem will go away. - Jonathan M Davis
Re: More optional parens concerns
Russel Winder wrote: On Sat, 2017-06-24 at 11:58 +0300, ketmar via Digitalmars-d-learn wrote: Russel Winder wrote: I note that: x.map!(…).array.sort is not valid, you have to have the parentheses on sort: x.map!(…).array.sort() Why? built-in property .sort kicks in and ruins the day. luckily, it will be completely removed in the upcoming major release. Ah, thanks. We like stuff being removed as well as added. sort and .reverse builtins was deprecated for a long time, and scheduled to be removed anyway. finally, this happens! (the patch is in git already)
Re: More optional parens concerns
On Sat, 2017-06-24 at 11:58 +0300, ketmar via Digitalmars-d-learn wrote: > Russel Winder wrote: > > > I note that: > > > > x.map!(…).array.sort > > > > is not valid, you have to have the parentheses on sort: > > > > x.map!(…).array.sort() > > > > Why? > > built-in property .sort kicks in and ruins the day. luckily, it will > be > completely removed in the upcoming major release. Ah, thanks. We like stuff being removed as well as added. -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Alias template parameter to a private function
Hi, I'm trying to call std.algorithm.iteration.filter with a private function as a predicate. Here's a reduced example code: // yo.d import std.algorithm; void moduleEntryPoint() { privateFunction1(); privateFunction2(); } private: void privateFunction1() { auto array = [0, 1, 2, 3, 4, 5]; auto result = filter!isValid(array); // error: 'isValid' is private } void privateFunction2() { auto array = [0, 1, 2, 3, 4, 5]; auto result = filter!isValid(array); // error: 'isValid' is private } bool isValid(int i) { return i % 2 == 0; } Here's the compiler output: /usr/include/dmd/phobos/std/algorithm/iteration.d(1132): Error: function yo.isValid is not accessible from module iteration yo.d(14): Error: template instance std.algorithm.iteration.filter!(isValid).filter!(int[]) error instantiating This seems like the compiler, when instanciating the calls to 'filter', is resolving 'isValid' from std.algorithm.iteration scope (however, this isn't actually the case, see below). I was expecting this identifier to be resolved from yo.d, where we have access to the private functions. Surprisingly, the following works: void privateFunction2() { static bool isValid(int i) { return i % 2 == 0; } auto array = [0, 1, 2, 3, 4, 5]; auto result = filter!isValid(array); // error: 'isValid' is private } This makes the instanciation of 'filter' "see" 'isValid', however, now, the other privateFunctions can't use it. Am I missing something here? Thanks!
Re: More optional parens concerns
Russel Winder wrote: I note that: x.map!(…).array.sort is not valid, you have to have the parentheses on sort: x.map!(…).array.sort() Why? built-in property .sort kicks in and ruins the day. luckily, it will be completely removed in the upcoming major release.
More optional parens concerns
I note that: x.map!(…).array.sort is not valid, you have to have the parentheses on sort: x.map!(…).array.sort() Why? -- Russel. = Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.win...@ekiga.net 41 Buckmaster Roadm: +44 7770 465 077 xmpp: rus...@winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder signature.asc Description: This is a digitally signed message part
Are padding bits always zero?
Hi everyone! Are there any guarantees about the values of padding bits in structs? Thanks, Honey
Re: Help me escape optional parens hell
ketmar wrote: Meta wrote: So I have no clue what I'm doing wrong. This is driving me insane. h. known $#^#$@^@%. enum SymName = ().stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there. i hope devs won't break string representation: i bet that there is ALOT of code that is using this trick. i myself borrowed it from some other module several years ago. and it looks that the module where i found it borrowed the trick from some another module. a really long history. ;-)
Re: Help me escape optional parens hell
Meta wrote: So I have no clue what I'm doing wrong. This is driving me insane. h. known $#^#$@^@%. enum SymName = ().stringof[2..$]; // this, instead of symbol.stringof dirty hack, let's hope that DMD devs won't change `.toString()` output (i.e. first two chars will always be "& "). besides this, i know no other way to stop compiler from calling the function there.
Re: Help me escape optional parens hell
ketmar wrote: `.toString()` toChars(). ;-)
Help me escape optional parens hell
The code: alias Response = Nullable!(string, "empty response (error)"); Response processMessage(string commandModule)(string message, bool isCommand) { import std.meta; import std.string; import std.traits; import command_uda; mixin("import " ~ commandModule ~ ';'); bool foundCommandMatch = false; foreach(symbol; getSymbolsByUDA!(mixin(commandModule), Command)) { enum commandUDA = getUDAs!(symbol, Command)[0]; auto commandPhrase = commandUDA.phrase == "" ? symbol.stringof : commandUDA.phrase; //Error: function signature> is not callable using argument types () auto commandPhrasePattern = regex(`^%s\s`.format(commandPhrase)); if (message.matchFirst(commandPhrasePattern) && !foundCommandMatch) { version(responseDebug) writeln("Matched command ", symbol.stringof, " with phrase '", commandPhrase, "'\n"); //Same issue return Response(symbol(message.strip())); } } return Response.init; } I've been banging my head against this and cannot figure out why `symbol.stringof` is being called instead of getting a string of the symbol. I tried to create a reduced test case but it works fine: import std.stdio; import std.traits; enum Attr; @Attr string test1() { return __FUNCTION__; } @Attr string test2() { return __FUNCTION__; } void process() { foreach (symbol; getSymbolsByUDA!(mixin(__MODULE__), Attr)) { writeln("The result of calling ", symbol.stringof, " is ", symbol()); } } void main() { process(); } So I have no clue what I'm doing wrong. This is driving me insane.
Re: Converting a ubyte[] to a struct with respect to endianness?
On 06/23/2017 10:18 PM, H. S. Teoh via Digitalmars-d-learn wrote: On Fri, Jun 23, 2017 at 10:10:22PM -0700, Ali Çehreli via Digitalmars-d-learn wrote: On 06/23/2017 09:26 PM, Felix wrote: That works, thanks! I've just tried this, which seems cleaner: import std.stdio; import std.system; import std.bitmanip; void ensureBigEndian(T)(ref T value) { if (endian == Endian.littleEndian) { value = *cast(T*)nativeToBigEndian(value).ptr; } This is wrong, you should be detecting the endianness of the input and use {big,little}EndianToNative instead. For example, if the input is big endian, you should use bigEndianToNative. Internally, if native is already big endian, it will do nothing; otherwise it will swap the endianness. This way you don't have to check the current machine's endianness yourself; you can just recompile on a machine of different endianness and it will Just Work. T Thanks. Something like this: import std.stdio; import std.system; import std.bitmanip; void ensureCorrectFromBigEndian(T)(ref T value) { value = bigEndianToNative!(T, T.sizeof)(*cast(ubyte[T.sizeof]*)); } struct S { uint u; } void main() { // Bytes on the wire ubyte[] bytes = [ 0, 0, 0, 13 ]; // Overlaying an object on those bytes S s = *cast(S*)bytes.ptr; void checkValue(uint expectedOnLE, uint expectedOnBE) { if (endian == Endian.littleEndian) { assert(s.u == expectedOnLE); } else if (endian == Endian.bigEndian) { assert(s.u == expectedOnBE); } else { assert(false, "What is this?"); } } // The value should be wrong no a little-endian system checkValue(218103808, 13); s.u.ensureCorrectFromBigEndian; // No matter what, now the result will be correct on any system checkValue(13, 13); } Ali