Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
June 21, 2017 Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
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-usage-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; } |
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to uncorroded | 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;
}
?
|
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to uncorroded | - 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 |
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to tetyys | On Wednesday, 21 June 2017 at 18:58:58 UTC, tetyys wrote:
> 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
>
Or simpler,
while (left)
left -= fread(buf[n-left .. $].ptr, ubyte.sizeof, left, fp);
|
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to tetyys | On Wednesday, 21 June 2017 at 18:58:58 UTC, tetyys wrote: > 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; > } > > ? 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'. |
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to uncorroded | 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 |
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 21 June 2017 at 19:11:44 UTC, Ali Çehreli wrote:
> 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
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.
|
June 21, 2017 Re: Using array slices with C-style fread() from file | ||||
---|---|---|---|---|
| ||||
Posted in reply to uncorroded | 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 |
Copyright © 1999-2021 by the D Language Foundation