| Thread overview | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 09, 2016 C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Is there a way to access a static array from D without knowing the size of the array? Let suppose there is an array, somewhere in lib.c. int tab[64]; and there is header file lib.h with following reference: extern int tab[]; How to declare `tab` in the D code without knowing the size of the array? In other words, how to map external declaration of the `tab` to the D code? | ||||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ciechowoj | On 8/9/16 9:53 AM, ciechowoj wrote:
> Is there a way to access a static array from D without knowing the size
> of the array?
>
> Let suppose there is an array, somewhere in lib.c.
>
> int tab[64];
>
> and there is header file lib.h with following reference:
>
> extern int tab[];
>
> How to declare `tab` in the D code without knowing the size of the
> array? In other words, how to map external declaration of the `tab` to
> the D code?
I think this should work:
extern extern(C) int[1] tab;
Then if you want to access the elements, use the tab.ptr[elem]
If it's a global variable, tack on __gshared.
-Steve
| |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 9 August 2016 at 14:01:17 UTC, Steven Schveighoffer wrote:
>
> I think this should work:
>
> extern extern(C) int[1] tab;
>
> Then if you want to access the elements, use the tab.ptr[elem]
>
> If it's a global variable, tack on __gshared.
>
> -Steve
I've already tried this and works (64-bit at least on linux). But is it portable?
No other way that allow to access the `tab` directly (without .ptr proxy) ?
| |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ciechowoj | Well extern extern(C) __gshared int[64] tab; | |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Kagamin | On Tuesday, 9 August 2016 at 14:25:15 UTC, Kagamin wrote:
> Well
> extern extern(C) __gshared int[64] tab;
My assumption is you do not know the size of the array.
| |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ciechowoj | On 8/9/16 10:09 AM, ciechowoj wrote: > On Tuesday, 9 August 2016 at 14:01:17 UTC, Steven Schveighoffer wrote: >> >> I think this should work: >> >> extern extern(C) int[1] tab; >> >> Then if you want to access the elements, use the tab.ptr[elem] >> >> If it's a global variable, tack on __gshared. >> > > I've already tried this and works (64-bit at least on linux). But is it > portable? Yes. D is designed to interface with C in certain ways, and this should be portable. > No other way that allow to access the `tab` directly (without ..ptr > proxy) ? Well, you can via properties: @property int* tabp() { return tab.ptr; } tabp[elem]; Essentially, tab is a symbol that points at some undetermined number of elements. Since it's undetermined, D doesn't allow safe easy access. If you did int *tab, then it would think the symbol points at a pointer. tab.ptr is a shortcut to &tab[0]. You could potentially do int tab, and then use (&tab)[elem]. Or if you know the number of elements, you can just declare them. If it were me, I'd access it via tab.ptr, because it *is* an unsafe operation and I'd want to highlight that for future readers. If something defines tab's length, I'd highly recommend wrapping the two: extern(C) int tabLength(); // mythical mechanism or no? @property int[] dtab { return tab.ptr[0 .. tabLength]; } -Steve | |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 8/9/16 11:41 AM, Steven Schveighoffer wrote:
> extern(C) int tabLength(); // mythical mechanism or no?
>
> @property int[] dtab { return tab.ptr[0 .. tabLength]; }
And I've used mythical syntax also! Should be:
@property int[] dtab() { return tab.ptr[0 .. tabLength]; }
-Steve
| |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Tuesday, 9 August 2016 at 15:41:08 UTC, Steven Schveighoffer wrote: > > Well, you can via properties: > > @property int* tabp() { return tab.ptr; } > > tabp[elem]; This is nice. The best would be to have it with the same name as original symbol, but I can't imagine how it could be done. > Essentially, tab is a symbol that points at some undetermined number of elements. Since it's undetermined, D doesn't allow safe easy access. > > If you did int *tab, then it would think the symbol points at a pointer. > > tab.ptr is a shortcut to &tab[0]. > > You could potentially do int tab, and then use (&tab)[elem]. > > Or if you know the number of elements, you can just declare them. > > If it were me, I'd access it via tab.ptr, because it *is* an unsafe operation and I'd want to highlight that for future readers. > > If something defines tab's length, I'd highly recommend wrapping the two: > > extern(C) int tabLength(); // mythical mechanism or no? > > @property int[] dtab { return tab.ptr[0 .. tabLength]; } And this is even better. However, I suppose you are right and I should stick to `tab.ptr`. | |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ciechowoj | On 8/9/16 2:46 PM, ciechowoj wrote:
> On Tuesday, 9 August 2016 at 15:41:08 UTC, Steven Schveighoffer wrote:
>>
>> Well, you can via properties:
>>
>> @property int* tabp() { return tab.ptr; }
>>
>> tabp[elem];
>
> This is nice. The best would be to have it with the same name as
> original symbol, but I can't imagine how it could be done.
D has an answer:
pragma(mangle, "tab")
extern extern(C) int[1] _ctab;
@property int* tab() { return _ctab.ptr; }
I still don't recommend doing this, for previously stated reasons.
-Steve
Disclaimer: D does not always have an answer. It only has MOST of the answers.
| |||
August 09, 2016 Re: C-binding external array. | ||||
|---|---|---|---|---|
| ||||
Posted in reply to ciechowoj | On 08/09/2016 11:46 AM, ciechowoj wrote:
> On Tuesday, 9 August 2016 at 15:41:08 UTC, Steven Schveighoffer wrote:
>> @property int* tabp() { return tab.ptr; }
>>
>> tabp[elem];
>
> This is nice. The best would be to have it with the same name as
> original symbol, but I can't imagine how it could be done.
Well, C's array symbol is used as a pointer to the first element and D allows array indexing for pointers as well.
Here is the C code:
// c.c
#include "stdio.h"
int tab[64];
int *get() {
return tab; // or &tab[0]
}
void info() {
printf("%p\n", tab);
}
void write_at(int i, int value) {
tab[i] = value;
}
int read_at(int i) {
return tab[i];
}
The D code uses the array as a pointer and then makes a slice at the very end:
// d.d
import std.stdio;
extern (C) {
int *get();
void info();
void write_at(int i, int value);
int read_at(int i);
}
void main() {
int *tab = get();
info();
writefln("0x%s", tab);
// make sure we can see what C writes
write_at(7, 77);
assert(tab[7] == 77);
// make sure C can read what we write
tab[42] = 42;
assert(read_at(42) == 42);
// If you know the size, use as a D array
int[] tab_D = tab[0..64];
writeln(tab_D);
}
Ali
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply