digitalmars.D.learn - Using array slices with C-style fread() from file
- uncorroded (27/27) Jun 21 2017 Hi all,
- tetyys (18/20) Jun 21 2017 What about this:
- tetyys (4/8) Jun 21 2017 Or simpler,
- uncorroded (5/25) Jun 21 2017 Thanks a lot! That works. Did not know about the .ptr for a
- =?UTF-8?Q?Ali_=c3=87ehreli?= (10/13) Jun 21 2017 'core.stdc.stdio.fread,fopen,fclose'.
- uncorroded (5/19) Jun 21 2017 Thanks! So @trusted is me guaranteeing to the compiler that this
- =?UTF-8?Q?Ali_=c3=87ehreli?= (8/13) Jun 21 2017 That's a good idea, which you can do yourself but I don't think you can
- =?UTF-8?Q?Ali_=c3=87ehreli?= (21/21) Jun 21 2017 - Fixed-length arrays are value types. You may not want to return them
Hi all, I am writing a program to read device /dev/urandom file to get some random bytes. I am trying to bypass D's GC as I know the length of the buffer needed. I tried using std.stdio.File and rawRead but File cannot be used with nogc. So I used core.stdc.stdio and used traditional C style. My code is here - https://dpaste.dzfl.pl/36e1df4cb99b (Also at end of post). I am using fread instead of read because /dev/urandom can be accessed by other programs (From this post - http://insanecoding.blogspot.in/2014/05/a-good-idea-with-bad-u age-devurandom.html ). As you can see from code, I ended up doing pointer arithmetic. Is there a way of making this work with D slices? Can they be used as C-style pointers? My D function used for getting random bytes: nogc ubyte[n] rand_bytes(uint n)() { import core.stdc.stdio; FILE *fp; fp = fopen("/dev/urandom", "r"); ubyte[n] buf; ubyte *bp = &buf[0]; uint bread = 0; while (bread < n) { auto toread = n - bread; auto read = fread(bp, ubyte.sizeof, toread, fp); bread += read; bp += read; } fclose(fp); return buf; }
Jun 21 2017
On Wednesday, 21 June 2017 at 18:49:01 UTC, uncorroded wrote:Is there a way of making this work with D slices? Can they be used as C-style pointers?What about this: nogc ubyte[n] rand_bytes(uint n)() { import core.stdc.stdio; FILE *fp; fp = fopen("/dev/urandom", "r"); ubyte[n] buf; uint bread = 0; while (bread < n) { auto toread = n - bread; auto read = fread(buf[bread .. $].ptr, ubyte.sizeof, toread, fp); bread += read; } fclose(fp); return buf; } ?
Jun 21 2017
On Wednesday, 21 June 2017 at 18:58:58 UTC, tetyys wrote:On Wednesday, 21 June 2017 at 18:49:01 UTC, uncorroded wrote:Or simpler, while (left) left -= fread(buf[n-left .. $].ptr, ubyte.sizeof, left, fp);Is there a way of making this work with D slices? Can they be used as C-style pointers?What about this
Jun 21 2017
On Wednesday, 21 June 2017 at 18:58:58 UTC, tetyys wrote:On Wednesday, 21 June 2017 at 18:49:01 UTC, uncorroded wrote:Thanks a lot! That works. Did not know about the .ptr for a slice. Is there any way of making the function with safe as well? I get the errors "cannot call system function 'core.stdc.stdio.fread,fopen,fclose'.Is there a way of making this work with D slices? Can they be used as C-style pointers?What about this: nogc ubyte[n] rand_bytes(uint n)() { import core.stdc.stdio; FILE *fp; fp = fopen("/dev/urandom", "r"); ubyte[n] buf; uint bread = 0; while (bread < n) { auto toread = n - bread; auto read = fread(buf[bread .. $].ptr, ubyte.sizeof, toread, fp); bread += read; } fclose(fp); return buf; } ?
Jun 21 2017
On 06/21/2017 12:06 PM, uncorroded wrote:Is there any way of making the function with safe as well? I get the errors "cannot call system function'core.stdc.stdio.fread,fopen,fclose'. trusted is exactly for that. It can be called from safe code: trusted nogc ubyte[n] rand_bytes(uint n)() { // ... } safe auto foo() { return rand_bytes!3(); } Ali
Jun 21 2017
On Wednesday, 21 June 2017 at 19:11:44 UTC, Ali Çehreli wrote:On 06/21/2017 12:06 PM, uncorroded wrote:Thanks! So trusted is me guaranteeing to the compiler that this function is safe? Is there any way of auditing this code through valgrind, etc. Also, thanks a lot for your book on D. It has been an invaluable resource in getting me started.Is there any way of making the function with safe as well? Iget theerrors "cannot call system function'core.stdc.stdio.fread,fopen,fclose'. trusted is exactly for that. It can be called from safe code: trusted nogc ubyte[n] rand_bytes(uint n)() { // ... } safe auto foo() { return rand_bytes!3(); } Ali
Jun 21 2017
On 06/21/2017 12:20 PM, uncorroded wrote:So trusted is me guaranteeing to the compiler that this function is safe?Yes and you shouldn't lie. :)Is there any way of auditing this code through valgrind, etc.That's a good idea, which you can do yourself but I don't think you can be sure beyond the tests that you've ran. There can always be corner cases where the library you use may not be memory-safe. You have to trust... :)invaluable resource in getting me started.Thank you! Makes me very happy to hear that. :) Ali
Jun 21 2017
- Fixed-length arrays are value types. You may not want to return them if n is very large. - Every array has the .ptr property that gives the pointer to the first element. - What can be helpful to you here is the fact that you can treat any memory as a slice: import core.stdc.stdlib; struct S { double d; } void main() { ubyte * p = cast(ubyte*)malloc(10); ubyte[] slice = p[0..10]; // 10 is number of elements // Another example with a struct object: auto objectCount = 7; S * objects = cast(S*)malloc(objectCount * S.sizeof); auto S_slice = objects[0..objectCount]; } Of course, you must be careful with slice lifetimes in this case; you shouldn't use the slices after freeing the memory. Ali
Jun 21 2017