digitalmars.D.learn - C-binding external array.
- ciechowoj (9/9) Aug 09 2016 Is there a way to access a static array from D without knowing
- Steven Schveighoffer (6/15) Aug 09 2016 I think this should work:
- ciechowoj (6/11) Aug 09 2016 I've already tried this and works (64-bit at least on linux). But
- Kagamin (2/2) Aug 09 2016 Well
- ciechowoj (2/4) Aug 09 2016 My assumption is you do not know the size of the array.
- Steven Schveighoffer (18/32) Aug 09 2016 Yes. D is designed to interface with C in certain ways, and this should
- Steven Schveighoffer (4/6) Aug 09 2016 And I've used mythical syntax also! Should be:
- ciechowoj (6/25) Aug 09 2016 This is nice. The best would be to have it with the same name as
- Steven Schveighoffer (9/18) Aug 09 2016 D has an answer:
- ciechowoj (3/9) Aug 10 2016 This is really interesting :).
- =?UTF-8?Q?Ali_=c3=87ehreli?= (11/23) Aug 10 2016 Better with some mixin magic:
- ciechowoj (4/15) Aug 10 2016 This is very tempting to use. The only thing that stops me from
- =?UTF-8?Q?Ali_=c3=87ehreli?= (44/50) Aug 09 2016 Well, C's array symbol is used as a pointer to the first element and D
- ciechowoj (2/15) Aug 10 2016 The problem is, I do not have a control over the C source code.
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?
Aug 09 2016
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
Aug 09 2016
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. -SteveI'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) ?
Aug 09 2016
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.
Aug 09 2016
On 8/9/16 10:09 AM, ciechowoj wrote:On Tuesday, 9 August 2016 at 14:01:17 UTC, Steven Schveighoffer wrote:Yes. D is designed to interface with C in certain ways, and this should be portable.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?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
Aug 09 2016
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
Aug 09 2016
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`.
Aug 09 2016
On 8/9/16 2:46 PM, ciechowoj wrote:On Tuesday, 9 August 2016 at 15:41:08 UTC, Steven Schveighoffer wrote: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.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.
Aug 09 2016
On Tuesday, 9 August 2016 at 19:16:42 UTC, Steven Schveighoffer wrote: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.This is really interesting :).
Aug 10 2016
On 08/10/2016 02:05 AM, ciechowoj wrote:On Tuesday, 9 August 2016 at 19:16:42 UTC, Steven Schveighoffer wrote:Better with some mixin magic: mixin template CArray(string symbol, T) { pragma(mangle, symbol) extern extern(C) __gshared mixin ("T[0] _c" ~ symbol ~ ";"); property mixin ("T* " ~ symbol ~ "() { return _c" ~ symbol ~ ".ptr; }"); } mixin CArray!("tab", int); tab[42] = 42; AliD 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.This is really interesting :).
Aug 10 2016
On Wednesday, 10 August 2016 at 15:07:52 UTC, Ali Çehreli wrote:On 08/10/2016 02:05 AM, ciechowoj wrote: Better with some mixin magic: mixin template CArray(string symbol, T) { pragma(mangle, symbol) extern extern(C) __gshared mixin ("T[0] _c" ~ symbol ~ ";"); property mixin ("T* " ~ symbol ~ "() { return _c" ~ symbol ~ ".ptr; }"); } mixin CArray!("tab", int); tab[42] = 42;This is very tempting to use. The only thing that stops me from doing that is I am unsure if the 'property' tab behaves in all contexts the same way the standard array behaves.
Aug 10 2016
On 08/09/2016 11:46 AM, ciechowoj wrote:On Tuesday, 9 August 2016 at 15:41:08 UTC, Steven Schveighoffer wrote: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); } Aliproperty 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.
Aug 09 2016
On Tuesday, 9 August 2016 at 19:16:46 UTC, Ali Çehreli wrote: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); } [...]The problem is, I do not have a control over the C source code.
Aug 10 2016