Re: Calling C functions

2020-06-30 Thread Jacob Carlborg via Digitalmars-d-learn
On Tuesday, 30 June 2020 at 12:22:15 UTC, Steven Schveighoffer 
wrote:



(i.e. one cannot use extern(D) functions for C callbacks).


I don't think that's a big issue. Honestly, I don't think it's an 
issue at all.


BTW, the order of arguments is not the only thing. Variadic 
functions in D and C are completely different. I don't think it's 
possible to implement a C style variadic function with D linkage 
(the language doesn't provide a syntax for it).


There's also D specific types which C cannot handle (like arrays 
and delegates).


I'm sure there are other differences in the ABIs.

--
/Jacob Carlborg


Re: Calling C functions

2020-06-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/30/20 3:00 AM, Kagamin wrote:

On Monday, 29 June 2020 at 19:55:59 UTC, Steven Schveighoffer wrote:
Yep, for sure. I'll file an issue. Anyone know why the calling 
convention would differ?


It's easier to enforce left to right evaluation order this way: 
arguments are pushed to stack as they are evaluated, which is pascal 
calling convention.


Easier, or more efficient? The cost seems high if it doesn't provide any 
efficiency benefits (i.e. one cannot use extern(D) functions for C 
callbacks).


In any case, I filed an issue: 
https://issues.dlang.org/show_bug.cgi?id=20993


-Steve


Re: Calling C functions

2020-06-30 Thread Kagamin via Digitalmars-d-learn
On Monday, 29 June 2020 at 19:55:59 UTC, Steven Schveighoffer 
wrote:
Yep, for sure. I'll file an issue. Anyone know why the calling 
convention would differ?


It's easier to enforce left to right evaluation order this way: 
arguments are pushed to stack as they are evaluated, which is 
pascal calling convention.


Re: Calling C functions

2020-06-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/29/20 1:50 PM, Jacob Carlborg wrote:

On Monday, 29 June 2020 at 16:34:33 UTC, Steven Schveighoffer wrote:

Are you sure? On the ABI page [1] , it says "The extern (C) and extern 
(D) calling convention matches the C calling convention used by the 
supported C compiler on the host system."


In that case the documentation is wrong. Here's an example showing the 
differences:


Yep, for sure. I'll file an issue. Anyone know why the calling 
convention would differ?


-Steve


Re: Calling C functions

2020-06-29 Thread Jacob Carlborg via Digitalmars-d-learn
On Monday, 29 June 2020 at 16:34:33 UTC, Steven Schveighoffer 
wrote:


Are you sure? On the ABI page [1] , it says "The extern (C) and 
extern (D) calling convention matches the C calling convention 
used by the supported C compiler on the host system."


In that case the documentation is wrong. Here's an example 
showing the differences:


$ cat foo.c
#include 

void foo(int a, int b)
{
printf("a=%d b=%d\n", a, b);
}
$ clang -c foo.c
$ cat main.d
pragma(mangle, "foo") extern (D) void foo_extern_d(int, int);
pragma(mangle, "foo") extern (C) void foo_extern_c(int, int);

void main()
{
foo_extern_d(1, 2);
foo_extern_c(1, 2);
}
$ dmd main.d foo.o
$ ./main
a=2 b=1
a=1 b=2

This is on macOS.

--
/Jacob Carlborg


Re: Calling C functions

2020-06-29 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/26/20 4:15 AM, Jacob Carlborg wrote:

On Friday, 26 June 2020 at 00:30:22 UTC, Denis wrote:

I have a two questions about calling C functions from D.

(1) When passing a D callback to a C function, is there a way to write 
the code without having to prefix the callback declaration with 
"extern(C)"?


It's not a big deal adding the prefix to the D function declaration. 
It just seems odd to me to prefix D code with "extern(C)". For 
example, the following code works:


  extern(C) void cfunc(void function(int));
  extern(C) void dcallback(int x) {...}    <-- Why extern(C)?
  cfunc();

Can this be rewritten, dropping the prefix from the second line? If 
not, it would be helpful to know why "extern(C)" is needed here too.


No, it cannot be dropped. `extern(C)` is required because C and D are 
using different calling conventions (D functions are also mangled). For 
example, D (at least DMD and LDC) are passing the arguments to the 
function in reverse.


Are you sure? On the ABI page [1] , it says "The extern (C) and extern 
(D) calling convention matches the C calling convention used by the 
supported C compiler on the host system."


I'm pretty sure you can use function pointers to D functions for C 
callbacks, and it should work.


-Steve

[1] https://dlang.org/spec/abi.html#function_calling_conventions


Re: Calling C functions

2020-06-26 Thread Jacob Carlborg via Digitalmars-d-learn

On 2020-06-26 18:54, Denis wrote:


OK, now this makes sense.

I tested calling the same callback function directly from D: it compiled 
and worked correctly. So at least prefixing the callback function with 
`extern(C)` doesn't prevent the rest of the D program from calling it too.


No, of course not. How would you otherwise call your `cfunc` function 
from your original example ;)


--
/Jacob Carlborg


Re: Calling C functions

2020-06-26 Thread Denis via Digitalmars-d-learn

On Friday, 26 June 2020 at 08:15:27 UTC, Jacob Carlborg wrote:

On Friday, 26 June 2020 at 00:30:22 UTC, Denis wrote:



  extern(C) void cfunc(void function(int));
  extern(C) void dcallback(int x) {...} <-- Why extern(C)?
  cfunc();

Can this be rewritten, dropping the prefix from the second 
line? If not, it would be helpful to know why "extern(C)" is 
needed here too.


No, it cannot be dropped. `extern(C)` is required because C and 
D are using different calling conventions (D functions are also 
mangled). For example, D (at least DMD and LDC) are passing the 
arguments to the function in reverse.


OK, now this makes sense.

I tested calling the same callback function directly from D: it 
compiled and worked correctly. So at least prefixing the callback 
function with `extern(C)` doesn't prevent the rest of the D 
program from calling it too.


(2) Is there a way to restrict the invocation of a linked C 
function to one specific D function?


[...]

For functions nested in a D language construct (class, struct, 
function) the compiler will always use the D mangling, instead 
of the C mangling. In theory it would be possible to workaround 
that by forcing the mangled name using `pragma(mangle)`, but 
for some reason the compiler doesn't allow `pragma(mangle)` 
inside a function body, on a nested function declaration.


You can wrap up everything in a struct, as follows:


I see.

Thank you very much for these explanations and code -- the 
insights are very helpful.


Denis


Re: Calling C functions

2020-06-26 Thread Jacob Carlborg via Digitalmars-d-learn

On Friday, 26 June 2020 at 00:30:22 UTC, Denis wrote:

I have a two questions about calling C functions from D.

(1) When passing a D callback to a C function, is there a way 
to write the code without having to prefix the callback 
declaration with "extern(C)"?


It's not a big deal adding the prefix to the D function 
declaration. It just seems odd to me to prefix D code with 
"extern(C)". For example, the following code works:


  extern(C) void cfunc(void function(int));
  extern(C) void dcallback(int x) {...} <-- Why extern(C)?
  cfunc();

Can this be rewritten, dropping the prefix from the second 
line? If not, it would be helpful to know why "extern(C)" is 
needed here too.


No, it cannot be dropped. `extern(C)` is required because C and D 
are using different calling conventions (D functions are also 
mangled). For example, D (at least DMD and LDC) are passing the 
arguments to the function in reverse.


(2) Is there a way to restrict the invocation of a linked C 
function to one specific D function?


If the C header is defined in one of the core.stdc libraries, 
the import statement can either be global or inside a specific 
D function -- both work. In contrast, when the C function 
prototype is written directly into the D program (as above), 
the linker complains unless this declaration is made global. If 
it's possible to restrict the scope of the C function to just 
one D function, I'll take advantage.


For functions nested in a D language construct (class, struct, 
function) the compiler will always use the D mangling, instead of 
the C mangling. In theory it would be possible to workaround that 
by forcing the mangled name using `pragma(mangle)`, but for some 
reason the compiler doesn't allow `pragma(mangle)` inside a 
function body, on a nested function declaration.


You can wrap up everything in a struct, as follows:

struct printf
{
pragma(mangle, "printf") extern (C) private static int 
printf(in char*, ...);


static int opCall(Args...)(Args args)
{
return printf(args);
}
}

void main()
{
printf("asd\n".ptr);
}

The `printf` function can be called from anywhere within the 
module, but not outside the module.


--
/Jacob Carlborg


Calling C functions

2020-06-25 Thread Denis via Digitalmars-d-learn

I have a two questions about calling C functions from D.

(1) When passing a D callback to a C function, is there a way to 
write the code without having to prefix the callback declaration 
with "extern(C)"?


It's not a big deal adding the prefix to the D function 
declaration. It just seems odd to me to prefix D code with 
"extern(C)". For example, the following code works:


  extern(C) void cfunc(void function(int));
  extern(C) void dcallback(int x) {...} <-- Why extern(C)?
  cfunc();

Can this be rewritten, dropping the prefix from the second line? 
If not, it would be helpful to know why "extern(C)" is needed 
here too.


(2) Is there a way to restrict the invocation of a linked C 
function to one specific D function?


If the C header is defined in one of the core.stdc libraries, the 
import statement can either be global or inside a specific D 
function -- both work. In contrast, when the C function prototype 
is written directly into the D program (as above), the linker 
complains unless this declaration is made global. If it's 
possible to restrict the scope of the C function to just one D 
function, I'll take advantage.


(I'm using dmd, if that makes a difference.)

Thanks


Re: Calling C functions

2010-12-09 Thread Steven Schveighoffer
On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor  
crypticmetapho...@gmail.com wrote:



I found this page that describes how to call c functions from D.

I found this page that describes how:
http://arsdnet.net/dtips/#cfunc

on that page he uses gcc, and I use dmc, but I get different results.  
This is what I did


// cfile.c file
extern int globalFromD;

void functionFromC(int a) {
globalFromD = a;
}
// end cfile.c

// dfile.d
extern(C) { // this is needed to make it available from C
 int globalFromD;
}
extern(C) { // also needed when listing the prototypes for your C  
functions

 void functionFromC(int);
}

import std.stdio; // for writefln

int main() {
 globalFromD = 100;
 writefln(%d, globalFromD);

 functionFromC(500);
 writefln(%d, globalFromD);

 return 0;
}
// end dfile.d

I compile with:
dmc -c cfile.c
And I get  an cfile.obj, which is the object code (.o in gcc).
Then I compile the D code
dmd dfile.d cfile.obj
and I get no errors, so I run it, the result:
// start result
C:\DCode\libtestdfile.exe
100
100

C:\DCode\libtest
// end result

Why is it still 100? It should be 500. I don't think functionFromC( int  
) is being called, and I can't really find any other sources that  
clearly explain how to do this simple stuff, so can anyone explain how  
to fix it?


I'm guessing that this is a later D2 compiler?  If so, then the default  
storage for globals is in Thread Local Storage (local to each thread).   
This could explain why it doesn't work, because globalFromD is in TLS in  
D-land, but in the normal global space in C-land.  But there is no  
declaration of the global-space version then, so I'm surprised it would  
compile then.


I'm really curious why this doesn't work but does compile.

What version of D compiler are you using?

When using dmd 2.050 on linux I get this error when compiling:

ste...@steve-laptop:~/testd$ gcc -c testc.c
ste...@steve-laptop:~/testd$ ~/dmd-2.050/linux/bin/dmd testcallc.d testc.o
/usr/bin/ld: globalFromD: TLS definition in testcallc.o section .tbss  
mismatches non-TLS reference in testc.o

testc.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
--- errorlevel 1

Maybe it's a bug in Windows dmd?

-Steve


Re: Calling C functions

2010-12-09 Thread CrypticMetaphor

On 12/9/2010 3:57 PM, Steven Schveighoffer wrote:

On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor
crypticmetapho...@gmail.com wrote:


I found this page that describes how to call c functions from D.

I found this page that describes how:
http://arsdnet.net/dtips/#cfunc

on that page he uses gcc, and I use dmc, but I get different results.
This is what I did

// cfile.c file
extern int globalFromD;

void functionFromC(int a) {
globalFromD = a;
}
// end cfile.c

// dfile.d
extern(C) { // this is needed to make it available from C
int globalFromD;
}
extern(C) { // also needed when listing the prototypes for your C
functions
void functionFromC(int);
}

import std.stdio; // for writefln

int main() {
globalFromD = 100;
writefln(%d, globalFromD);

functionFromC(500);
writefln(%d, globalFromD);

return 0;
}
// end dfile.d

I compile with:
dmc -c cfile.c
And I get an cfile.obj, which is the object code (.o in gcc).
Then I compile the D code
dmd dfile.d cfile.obj
and I get no errors, so I run it, the result:
// start result
C:\DCode\libtestdfile.exe
100
100

C:\DCode\libtest
// end result

Why is it still 100? It should be 500. I don't think functionFromC(
int ) is being called, and I can't really find any other sources that
clearly explain how to do this simple stuff, so can anyone explain how
to fix it?


I'm guessing that this is a later D2 compiler? If so, then the default
storage for globals is in Thread Local Storage (local to each thread).
This could explain why it doesn't work, because globalFromD is in TLS in
D-land, but in the normal global space in C-land. But there is no
declaration of the global-space version then, so I'm surprised it would
compile then.

I'm really curious why this doesn't work but does compile.

What version of D compiler are you using?

When using dmd 2.050 on linux I get this error when compiling:

ste...@steve-laptop:~/testd$ gcc -c testc.c
ste...@steve-laptop:~/testd$ ~/dmd-2.050/linux/bin/dmd testcallc.d testc.o
/usr/bin/ld: globalFromD: TLS definition in testcallc.o section .tbss
mismatches non-TLS reference in testc.o
testc.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
--- errorlevel 1

Maybe it's a bug in Windows dmd?

-Steve


Yeah I am using D2

dmc version: 8.42n
dmd version: 2.050

Windows XP. But yeah, it compiles

here is a screenshot:
http://img813.imageshack.us/img813/8230/testu.gif

So I gotta read more about threads eh? But that's all the way at the end 
of the book :-(


But anyway, it should not compile right?

Should I submit a bug report or something?
And how I supposed to call the c function?


Re: Calling C functions

2010-12-09 Thread Steven Schveighoffer
On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor  
crypticmetapho...@gmail.com wrote:



On 12/9/2010 3:57 PM, Steven Schveighoffer wrote:

On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor
crypticmetapho...@gmail.com wrote:


I found this page that describes how to call c functions from D.

I found this page that describes how:
http://arsdnet.net/dtips/#cfunc

on that page he uses gcc, and I use dmc, but I get different results.
This is what I did

// cfile.c file
extern int globalFromD;

void functionFromC(int a) {
globalFromD = a;
}
// end cfile.c

// dfile.d
extern(C) { // this is needed to make it available from C
int globalFromD;
}
extern(C) { // also needed when listing the prototypes for your C
functions
void functionFromC(int);
}

import std.stdio; // for writefln

int main() {
globalFromD = 100;
writefln(%d, globalFromD);

functionFromC(500);
writefln(%d, globalFromD);

return 0;
}
// end dfile.d

I compile with:
dmc -c cfile.c
And I get an cfile.obj, which is the object code (.o in gcc).
Then I compile the D code
dmd dfile.d cfile.obj
and I get no errors, so I run it, the result:
// start result
C:\DCode\libtestdfile.exe
100
100

C:\DCode\libtest
// end result

Why is it still 100? It should be 500. I don't think functionFromC(
int ) is being called, and I can't really find any other sources that
clearly explain how to do this simple stuff, so can anyone explain how
to fix it?


I'm guessing that this is a later D2 compiler? If so, then the default
storage for globals is in Thread Local Storage (local to each thread).
This could explain why it doesn't work, because globalFromD is in TLS in
D-land, but in the normal global space in C-land. But there is no
declaration of the global-space version then, so I'm surprised it would
compile then.

I'm really curious why this doesn't work but does compile.

What version of D compiler are you using?

When using dmd 2.050 on linux I get this error when compiling:

ste...@steve-laptop:~/testd$ gcc -c testc.c
ste...@steve-laptop:~/testd$ ~/dmd-2.050/linux/bin/dmd testcallc.d  
testc.o

/usr/bin/ld: globalFromD: TLS definition in testcallc.o section .tbss
mismatches non-TLS reference in testc.o
testc.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
--- errorlevel 1

Maybe it's a bug in Windows dmd?

-Steve


Yeah I am using D2

dmc version: 8.42n
dmd version: 2.050

Windows XP. But yeah, it compiles

here is a screenshot:
http://img813.imageshack.us/img813/8230/testu.gif

So I gotta read more about threads eh? But that's all the way at the end  
of the book :-(


No, not really.  TLS is related to threads, but you don't really have to  
understand how threads work to understand where things are stored.


I don't know where it is in the book, but try looking for Thread Local  
Storage in the index?



But anyway, it should not compile right?

Should I submit a bug report or something?


Yes please, and be sure to specify that it correctly does not compile on  
linux. http://d.puremagic.com/issues/enter_bug.cgi



And how I supposed to call the c function?


Mark the extern(C) integer as __gshared in D.  That will put it in the  
global namespace instead of TLS.


e.g.:

extern(C) { // this is needed to make it available from C
  __gshared int globalFromD;
}

-Steve


Re: Calling C functions

2010-12-09 Thread Andrej Mitrovic
I know I prefer using shared() when interfacing with C.

I've tried using __gshared once when interfacing with C code. But I
had crashes all the time, using shared instead made my app stable
again. It might be related to the way the C code worked, since
multiple threads were involved. Anyway.. that's my experience with
gshared..

On 12/9/10, Steven Schveighoffer schvei...@yahoo.com wrote:
 On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor
 crypticmetapho...@gmail.com wrote:

 On 12/9/2010 3:57 PM, Steven Schveighoffer wrote:
 On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor
 crypticmetapho...@gmail.com wrote:

 I found this page that describes how to call c functions from D.

 I found this page that describes how:
 http://arsdnet.net/dtips/#cfunc

 on that page he uses gcc, and I use dmc, but I get different results.
 This is what I did

 // cfile.c file
 extern int globalFromD;

 void functionFromC(int a) {
 globalFromD = a;
 }
 // end cfile.c

 // dfile.d
 extern(C) { // this is needed to make it available from C
 int globalFromD;
 }
 extern(C) { // also needed when listing the prototypes for your C
 functions
 void functionFromC(int);
 }

 import std.stdio; // for writefln

 int main() {
 globalFromD = 100;
 writefln(%d, globalFromD);

 functionFromC(500);
 writefln(%d, globalFromD);

 return 0;
 }
 // end dfile.d

 I compile with:
 dmc -c cfile.c
 And I get an cfile.obj, which is the object code (.o in gcc).
 Then I compile the D code
 dmd dfile.d cfile.obj
 and I get no errors, so I run it, the result:
 // start result
 C:\DCode\libtestdfile.exe
 100
 100

 C:\DCode\libtest
 // end result

 Why is it still 100? It should be 500. I don't think functionFromC(
 int ) is being called, and I can't really find any other sources that
 clearly explain how to do this simple stuff, so can anyone explain how
 to fix it?

 I'm guessing that this is a later D2 compiler? If so, then the default
 storage for globals is in Thread Local Storage (local to each thread).
 This could explain why it doesn't work, because globalFromD is in TLS in
 D-land, but in the normal global space in C-land. But there is no
 declaration of the global-space version then, so I'm surprised it would
 compile then.

 I'm really curious why this doesn't work but does compile.

 What version of D compiler are you using?

 When using dmd 2.050 on linux I get this error when compiling:

 ste...@steve-laptop:~/testd$ gcc -c testc.c
 ste...@steve-laptop:~/testd$ ~/dmd-2.050/linux/bin/dmd testcallc.d
 testc.o
 /usr/bin/ld: globalFromD: TLS definition in testcallc.o section .tbss
 mismatches non-TLS reference in testc.o
 testc.o: could not read symbols: Bad value
 collect2: ld returned 1 exit status
 --- errorlevel 1

 Maybe it's a bug in Windows dmd?

 -Steve

 Yeah I am using D2

 dmc version: 8.42n
 dmd version: 2.050

 Windows XP. But yeah, it compiles

 here is a screenshot:
 http://img813.imageshack.us/img813/8230/testu.gif

 So I gotta read more about threads eh? But that's all the way at the end
 of the book :-(

 No, not really.  TLS is related to threads, but you don't really have to
 understand how threads work to understand where things are stored.

 I don't know where it is in the book, but try looking for Thread Local
 Storage in the index?

 But anyway, it should not compile right?

 Should I submit a bug report or something?

 Yes please, and be sure to specify that it correctly does not compile on
 linux. http://d.puremagic.com/issues/enter_bug.cgi

 And how I supposed to call the c function?

 Mark the extern(C) integer as __gshared in D.  That will put it in the
 global namespace instead of TLS.

 e.g.:

 extern(C) { // this is needed to make it available from C
__gshared int globalFromD;
 }

 -Steve



Re: Calling C functions

2010-12-09 Thread Steven Schveighoffer
On Thu, 09 Dec 2010 11:38:00 -0500, Andrej Mitrovic  
andrej.mitrov...@gmail.com wrote:



I know I prefer using shared() when interfacing with C.

I've tried using __gshared once when interfacing with C code. But I
had crashes all the time, using shared instead made my app stable
again. It might be related to the way the C code worked, since
multiple threads were involved. Anyway.. that's my experience with
gshared..


__gshared is the equivalent of what normal globals used to be (in D1 and  
earlier versions of D2).  It's the same as a global variable in C.


shared is exactly the same as __gshared except the compiler inserts memory  
barriers around reads/writes (the C compiler does not), and shared is a  
type modifier, so it's available in the TypeInfo of the variable.  Some  
parts of the runtime use that to determine certain behaviors, and I am  
aware of one problem with __gshared that needs to be documented -- array  
appending.


__gshared is unprotected sharing, and the type system is not aware that it  
is shared.  Can you remember what specifically you were doing with the  
variable?


BTW, __gshared should have no problems in a single-threadded app.

-Steve


On 12/9/10, Steven Schveighoffer schvei...@yahoo.com wrote:

On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor
crypticmetapho...@gmail.com wrote:

And how I supposed to call the c function?


Mark the extern(C) integer as __gshared in D.  That will put it in the
global namespace instead of TLS.

e.g.:

extern(C) { // this is needed to make it available from C
   __gshared int globalFromD;
}


Re: Calling C functions

2010-12-09 Thread CrypticMetaphor

On 12/9/2010 5:28 PM, Steven Schveighoffer wrote:

On Thu, 09 Dec 2010 10:15:59 -0500, CrypticMetaphor
crypticmetapho...@gmail.com wrote:


On 12/9/2010 3:57 PM, Steven Schveighoffer wrote:

On Thu, 09 Dec 2010 09:37:03 -0500, CrypticMetaphor
crypticmetapho...@gmail.com wrote:


I found this page that describes how to call c functions from D.

I found this page that describes how:
http://arsdnet.net/dtips/#cfunc

on that page he uses gcc, and I use dmc, but I get different results.
This is what I did

// cfile.c file
extern int globalFromD;

void functionFromC(int a) {
globalFromD = a;
}
// end cfile.c

// dfile.d
extern(C) { // this is needed to make it available from C
int globalFromD;
}
extern(C) { // also needed when listing the prototypes for your C
functions
void functionFromC(int);
}

import std.stdio; // for writefln

int main() {
globalFromD = 100;
writefln(%d, globalFromD);

functionFromC(500);
writefln(%d, globalFromD);

return 0;
}
// end dfile.d

I compile with:
dmc -c cfile.c
And I get an cfile.obj, which is the object code (.o in gcc).
Then I compile the D code
dmd dfile.d cfile.obj
and I get no errors, so I run it, the result:
// start result
C:\DCode\libtestdfile.exe
100
100

C:\DCode\libtest
// end result

Why is it still 100? It should be 500. I don't think functionFromC(
int ) is being called, and I can't really find any other sources that
clearly explain how to do this simple stuff, so can anyone explain how
to fix it?


I'm guessing that this is a later D2 compiler? If so, then the default
storage for globals is in Thread Local Storage (local to each thread).
This could explain why it doesn't work, because globalFromD is in TLS in
D-land, but in the normal global space in C-land. But there is no
declaration of the global-space version then, so I'm surprised it would
compile then.

I'm really curious why this doesn't work but does compile.

What version of D compiler are you using?

When using dmd 2.050 on linux I get this error when compiling:

ste...@steve-laptop:~/testd$ gcc -c testc.c
ste...@steve-laptop:~/testd$ ~/dmd-2.050/linux/bin/dmd testcallc.d
testc.o
/usr/bin/ld: globalFromD: TLS definition in testcallc.o section .tbss
mismatches non-TLS reference in testc.o
testc.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
--- errorlevel 1

Maybe it's a bug in Windows dmd?

-Steve


Yeah I am using D2

dmc version: 8.42n
dmd version: 2.050

Windows XP. But yeah, it compiles

here is a screenshot:
http://img813.imageshack.us/img813/8230/testu.gif

So I gotta read more about threads eh? But that's all the way at the
end of the book :-(


No, not really. TLS is related to threads, but you don't really have to
understand how threads work to understand where things are stored.

I don't know where it is in the book, but try looking for Thread Local
Storage in the index?


But anyway, it should not compile right?

Should I submit a bug report or something?


Yes please, and be sure to specify that it correctly does not compile on
linux. http://d.puremagic.com/issues/enter_bug.cgi


And how I supposed to call the c function?


Mark the extern(C) integer as __gshared in D. That will put it in the
global namespace instead of TLS.

e.g.:

extern(C) { // this is needed to make it available from C
__gshared int globalFromD;
}

-Steve


Alright then!

I submitted a my first bug report and added __gshared in front of 
globalFromD and the output was:


100
500

So it worked. thanks!


Re: Calling C functions

2010-12-09 Thread Andrej Mitrovic
On 12/9/10, Steven Schveighoffer schvei...@yahoo.com wrote:
 __gshared is unprotected sharing, and the type system is not aware that it
 is shared.  Can you remember what specifically you were doing with the
 variable?

My dev PC is in repairs right now so I don't have the code atm. It's a
project that works with audio devices and does some basic processing
on audio data.

But from what I can recall I would pass my D callback function to C,
which would call the callback with an interrupt or very-high level
priority thread (it depends on the device driver implementation) at
many intervals per second. The D callback would do some processing,
update one structure variable (e.g. struct status), and return.
Inside main() I had an infinite loop which would wait for the device
driver to stop calling the callback. One way of knowing if the device
driver stopped is to check a flag inside the struct, e.g. a boolean
status.done.

The problem I was having at first was that the status struct inside
the callback was a new TLS variable, and the one main() was seeing was
a distinct variable. So main() would never see the updated struct.
I've tried marking the struct with __gshared, but this would
immediately crash my application. Using shared() instead fixed this
problem. This was using DMD 2.048 and I haven't tried newer versions
yet.

Of course, there are much better ways of notifying when the device
driver is done instead of polling the status.done flag all the time.
For example, with PortAudio (an audio library) I can use message
passing to notify my foreground thread that the background (working)
thread is done, or that the device driver has suddenly stopped
working. I could do the same with my first project, but PortAudio is a
mature and stable library so I've decided not to deal with device
drivers directly in my D code (otherwise I would have to write code
for all the audio device driver standards -- ASIO, WDM, CoreAudio, etc
etc..).


Re: Calling C functions

2010-12-09 Thread Steven Schveighoffer
On Thu, 09 Dec 2010 12:24:05 -0500, Andrej Mitrovic  
andrej.mitrov...@gmail.com wrote:



On 12/9/10, Steven Schveighoffer schvei...@yahoo.com wrote:
__gshared is unprotected sharing, and the type system is not aware that  
it

is shared.  Can you remember what specifically you were doing with the
variable?


My dev PC is in repairs right now so I don't have the code atm. It's a
project that works with audio devices and does some basic processing
on audio data.

But from what I can recall I would pass my D callback function to C,
which would call the callback with an interrupt or very-high level
priority thread (it depends on the device driver implementation) at
many intervals per second. The D callback would do some processing,
update one structure variable (e.g. struct status), and return.
Inside main() I had an infinite loop which would wait for the device
driver to stop calling the callback. One way of knowing if the device
driver stopped is to check a flag inside the struct, e.g. a boolean
status.done.


Multi-threadded code must do it's own handling of shared reads/writes to  
__gshared data, such as protecting it with a mutex.  Even with shared, it  
does not guarantee multiple operations are atomic (for example reading two  
members of a shared struct).


-Steve


Re: Calling C functions

2010-12-09 Thread Jesse Phillips
CrypticMetaphor Wrote:

 On 12/9/2010 5:28 PM, Steven Schveighoffer wrote:

  Yes please, and be sure to specify that it correctly does not compile on
  linux. http://d.puremagic.com/issues/enter_bug.cgi

  -Steve
 
 Alright then!
 
 I submitted a my first bug report and added __gshared in front of 
 globalFromD and the output was:
 
 100
 500
 
 So it worked. thanks!

It is a linker bug, so Oplink is at fault. What is the bug number you submitted?


Re: Calling C functions

2010-12-09 Thread Adam Ruppe
I almost forgot I wrote that dtips page! Thanks for bringing it up.

I just updated it to include a brief note on __gshared. The rest of it should
still work, though. Calling C functions is pretty easy.


Re: Calling C functions

2010-12-09 Thread CrypticMetaphor

On 12/9/2010 10:04 PM, Jesse Phillips wrote:

CrypticMetaphor Wrote:
It is a linker bug, so Oplink is at fault. What is the bug number you submitted?


bug number: 5337

http://d.puremagic.com/issues/show_bug.cgi?id=5337