digitalmars.D - Passing D strings to C
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (53/53) Dec 21 2005 For a library wrapper I'm working on, there is
- Jarrett Billingsley (8/14) Dec 21 2005 I'd say go with approach B as well, as I'd imagine the counted-string C
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (9/15) Dec 21 2005 They are the same size (i.e 8 bytes), but seem to be passed differently?
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (5/7) Dec 21 2005 Make that "uint64_t" (i.e. "ulong" in D, and "unsigned long long" in C)
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (20/45) Dec 22 2005 This was the chosen solution, and it worked out OK...
For a library wrapper I'm working on, there is
a need to pass some strings from D over to C...
This C library is rather flexible, and allows both
of a single "char *" parameter (zero-terminated),
but also a pair of parameters: "char *", "size_t"
(for this particular application, the strings will
be in UTF-8/ASCII format and won't contain any NULs)
Will it work to just pass the D strings over as they
are then, or do I need to copy/zero-terminate them
going out and then count/strlen them when coming in ?
Sounds like that means some extra looping and copying ?
(something I was hoping to avoid here, now that I can)
But ran into something of a snag with the (missing) ABI for
arrays in D, so I'm wondering what the best approach is here.
(i.e. DMD and GDC have two *different* approaches to passing
arrays, the main difference is that GDC is going 64 bit...)
So, the main question here is should I use a) :
=============================================
C:
extern void foo(unsigned char *str);
extern unsigned char *bar(void);
D:
extern(C) void foo(char* str);
extern(C) char* bar();
char[] s;
foo(std.string.toStringz(s));
s = std.string.toString(bar());
Or, should I go with the more "efficient" b) :
============================================
C:
typedef struct dstr {
size_t length;
const unsigned char *ptr;
} dstr;
#ifndef __GDC__
typedef unsigned long long dstrret; // DMD
#else
typedef dstr dstrret; // GDC
#endif
extern void foo(dstr str);
extern dstrret bar(void);
D:
extern(C) void foo(char[] str);
extern(C) char[] bar();
char[] s;
foo(s);
s = bar();
That is: the ugly and slow D, or the neat and fast D ? :)
(but thinking it could be a problem if DMD ever goes 64?
So maybe it is "safer" to use the toString(z) approach?)
--anders
PS. I'm leaning towards approach b), even if less portable
(i.e. the C code must know which D compiler is used...)
Dec 21 2005
"Anders F Björklund" <afb algonet.se> wrote in message
news:dobf2q$1jnf$1 digitaldaemon.com...
That is: the ugly and slow D, or the neat and fast D ? :)
(but thinking it could be a problem if DMD ever goes 64?
So maybe it is "safer" to use the toString(z) approach?)
--anders
PS. I'm leaning towards approach b), even if less portable
(i.e. the C code must know which D compiler is used...)
I'd say go with approach B as well, as I'd imagine the counted-string C
functions will function faster as well. But I'm not really getting the
problem - the dstr struct and an unsigned long long are the exact same size,
aren't they? So should it really matter the structure that the C version
uses, as long as it's 64 bits of data? Or has the "64-bit change in GDC"
(which I know nothing about) not happened yet?
Dec 21 2005
Jarrett Billingsley wrote:I'd say go with approach B as well, as I'd imagine the counted-string C functions will function faster as well. But I'm not really getting the problem - the dstr struct and an unsigned long long are the exact same size, aren't they? So should it really matter the structure that the C version uses, as long as it's 64 bits of data? Or has the "64-bit change in GDC" (which I know nothing about) not happened yet?They are the same size (i.e 8 bytes), but seem to be passed differently? Or at least DMD doesn't work with a struct and GDC not with a uint128_t. The "64-bit change" refers to David getting GDC ready to do 64-bits... http://www.digitalmars.com/drn-bin/wwwnews?D.gnu/1567 Note: There could be other reasons for using a struct instead of an integer. I just assumed it had something to do with being able to move easier ? --anders
Dec 21 2005
I wrote, mistakenly:They are the same size (i.e 8 bytes), but seem to be passed differently? Or at least DMD doesn't work with a struct and GDC not with a uint128_t.Make that "uint64_t" (i.e. "ulong" in D, and "unsigned long long" in C) And this was for the return value, using a struct as a parameter works OK in both compilers. (I assume they're just passed on the stack anyway) --anders
Dec 21 2005
Or, should I go with the more "efficient" b) : ============================================ C: typedef struct dstr { size_t length; const unsigned char *ptr; } dstr; #ifndef __GDC__ typedef unsigned long long dstrret; // DMD #else typedef dstr dstrret; // GDC #endif extern void foo(dstr str); extern dstrret bar(void); D: extern(C) void foo(char[] str); extern(C) char[] bar(); char[] s; foo(s); s = bar();That is: the ugly and slow D, or the neat and fast D ? :)This was the chosen solution, and it worked out OK... Here was the Makefile snippet that I used, to choose between the two methods of returning arrays back to D: OS=$(shell uname) ARCH=$(shell arch | sed -e s/i.86/x86/ ) ifeq ("$(OS) $(ARCH)","Linux x86") CXX = g++ -D__DMD__ DMD = dmd else ifeq ("$(OS) $(ARCH)","Darwin ppc") CXX = g++ -D__GDC__ DMD = gdmd else CXX = g++ -D__GDC__ DMD = gdmd endif endif Windows is handled in a separate Makefile altogether. (which is using CXX = dmc and DMD = dmd, naturally...) --anders
Dec 22 2005









=?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> 