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