www.digitalmars.com         C & C++   DMDScript  

D - Interfacing to C global variables ?

reply "Achilleas Margaritis" <axilmar in.gr> writes:
I've made a DLL with VC++ which contains two symbols:

DLL_API int value = 10;

DLL_API int *get_value_addr()
{
    return &value;
}

Then I used implib.exe to make a dll.lib for using with D.

Then I made the following D program to test access to DLL symbols:

import std.c.stdio;

extern(C) int value;
extern(C) int* get_value_addr();

int main(char[][] args)
{
     printf("value=%i\n", value);
     printf("addrof(value)=%p\n", &value);
     printf("get_value_addr=%p\n", get_value_addr());
     printf("*get_value_addr=%i\n", *get_value_addr());
     return 0;
}

The program output is:

value=0
addrof(value)=004130E0
get_value_addr=10006030
*get_value_addr=10

Which means that I can't access a C global variable from D; the function is
accessed ok, but the global variable is not.

Is this a bug ? is there some option that I should pass at the compiler ?

I am trying to port the Allegro multimedia library to D. Allegro functions
work ok, but Allegro global variables can't be accessed.
Apr 25 2004
next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6gejo$1r7v$1 digitaldaemon.com...
 I've made a DLL with VC++ which contains two symbols:

 DLL_API int value = 10;

 DLL_API int *get_value_addr()
 {
     return &value;
 }

 Then I used implib.exe to make a dll.lib for using with D.

 Then I made the following D program to test access to DLL symbols:

 import std.c.stdio;

 extern(C) int value;
 extern(C) int* get_value_addr();

 int main(char[][] args)
 {
      printf("value=%i\n", value);
      printf("addrof(value)=%p\n", &value);
      printf("get_value_addr=%p\n", get_value_addr());
      printf("*get_value_addr=%i\n", *get_value_addr());
      return 0;
 }

 The program output is:

 value=0
 addrof(value)=004130E0
 get_value_addr=10006030
 *get_value_addr=10

 Which means that I can't access a C global variable from D; the function is
 accessed ok, but the global variable is not.

I've *never* once seen a good reason to export data, rather than functions providing access to data, from a DLL. I recommend you change the design. (btw, for anyone who wants to tell me about exporting static class variables from DLLs, I acknowledge the technical feasibility of such things, but suggest that it's notionally a very bad idea still. basic_string::npos? No thanks!)
Apr 25 2004
parent reply "Achilleas Margaritis" <axilmar in.gr> writes:
 I've *never* once seen a good reason to export data, rather than functions
 providing access to data, from a DLL. I recommend you change the design.

I agree, but Allegro is not mine... It is a big library, which you can find it here: www.allegro.cc Do you know if exported data can be accessed from D ? if not, I would have to make an additional DLL with the functions which provide access to Allegro's global data.
Apr 25 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
Why not link in with a C static lib, for which you write a D layer. (Look at
recls for an example, albeit it's far larger than what you may need here, but
it'll give you the general idea of mapping from another language.)

"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6gjms$233m$1 digitaldaemon.com...
 I've *never* once seen a good reason to export data, rather than functions
 providing access to data, from a DLL. I recommend you change the design.

I agree, but Allegro is not mine... It is a big library, which you can find it here: www.allegro.cc Do you know if exported data can be accessed from D ? if not, I would have to make an additional DLL with the functions which provide access to Allegro's global data.

Apr 25 2004
parent reply "Achilleas Margaritis" <axilmar in.gr> writes:
"Matthew" <matthew.hat stlsoft.dot.org> wrote in message
news:c6glbu$25m6$1 digitaldaemon.com...
 Why not link in with a C static lib, for which you write a D layer. (Look

 recls for an example, albeit it's far larger than what you may need here,

 it'll give you the general idea of mapping from another language.)

But D is supposed to interface directly with C. Anyway, a layer is not really needed: allegro is usable from D, except for global variables. I will have to write a short DLL with getters/setters of the global variables.
Apr 25 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6h151$2oao$1 digitaldaemon.com...
 "Matthew" <matthew.hat stlsoft.dot.org> wrote in message
 news:c6glbu$25m6$1 digitaldaemon.com...
 Why not link in with a C static lib, for which you write a D layer. (Look

 recls for an example, albeit it's far larger than what you may need here,

 it'll give you the general idea of mapping from another language.)

But D is supposed to interface directly with C. Anyway, a layer is not really needed: allegro is usable from D, except for global variables. I will have to write a short DLL with getters/setters of the global variables.

I'm saying you don't need to have it as a DLL, just a bit of linked-in C.
Apr 25 2004
parent reply "Achilleas Margaritis" <axilmar in.gr> writes:
 I'm saying you don't need to have it as a DLL, just a bit of linked-in C.

Allegro is already distributed as a DLL (as well as a static library), so one would use the same code either from C or D. There is no need to bloat one's computer with my own version.
Apr 25 2004
parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
No, no! You're not getting me

C client code can "see" variables exported from DLLs. D cannot.

So, why not just have a *very* thin wrapper written in C, with suitable D
declarations, for getting what you want at almost no cost?

"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6hdn4$bfc$1 digitaldaemon.com...
 I'm saying you don't need to have it as a DLL, just a bit of linked-in C.

Allegro is already distributed as a DLL (as well as a static library), so one would use the same code either from C or D. There is no need to bloat one's computer with my own version.

Apr 25 2004
parent Achilleas Margaritis <Achilleas_member pathlink.com> writes:
In article <c6hg63$f96$1 digitaldaemon.com>, Matthew says...
No, no! You're not getting me

C client code can "see" variables exported from DLLs. D cannot.

So, why not just have a *very* thin wrapper written in C, with suitable D
declarations, for getting what you want at almost no cost?

But this is exactly what I have done. I just did not do it for the full Allegro API; I did it for global variables only: I wrapped all global variables in getters/setters. It works fine.
Apr 26 2004
prev sibling next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Achilleas Margaritis schrieb:

 Which means that I can't access a C global variable from D; the function is
 accessed ok, but the global variable is not.
 
 Is this a bug ? is there some option that I should pass at the compiler ?

This is a principal limitation of DLLs. Variables don't get exported.
 I am trying to port the Allegro multimedia library to D. Allegro functions
 work ok, but Allegro global variables can't be accessed.

Can you compile Allegro with DMC? If i remember correctly, Allegro is not designed to be linked dynamically. BTW, why Allegro and not libSDL, which was already ported by someone? -eye
Apr 25 2004
parent reply "Achilleas Margaritis" <axilmar in.gr> writes:
 If i remember correctly, Allegro is not designed to be linked dynamically.

Oh yes, it does. It comes in 2 flavors: dynamic, in form of DLL, and static.
 BTW, why Allegro and not libSDL, which was already ported by someone?

SDL is not the same with Allegro: All SDL does is provide access to the framebuffer and mouse/keyboard input, whereas Allegro can do this and sound, 3d, gui, drawing routines, filesystem, compression, sprites, and lots of other things SDL does not do.
Apr 25 2004
parent J Anderson <REMOVEanderson badmama.com.au> writes:
Achilleas Margaritis wrote:

If i remember correctly, Allegro is not designed to be linked dynamically.
    

Oh yes, it does. It comes in 2 flavors: dynamic, in form of DLL, and static.
BTW, why Allegro and not libSDL, which was already ported by someone?
    

SDL is not the same with Allegro: All SDL does is provide access to the framebuffer and mouse/keyboard input, whereas Allegro can do this and sound, 3d, gui, drawing routines, filesystem, compression, sprites, and lots of other things SDL does not do.

of those other things. -- -Anderson: http://badmama.com.au/~anderson/
Apr 25 2004
prev sibling parent reply "Walter" <newshound digitalmars.com> writes:
"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6gejo$1r7v$1 digitaldaemon.com...
 Which means that I can't access a C global variable from D; the function

 accessed ok, but the global variable is not.

 Is this a bug ? is there some option that I should pass at the compiler ?

 I am trying to port the Allegro multimedia library to D. Allegro functions
 work ok, but Allegro global variables can't be accessed.

The problem is that, in D, a declaration is a definition. So int x; will declare and define x. The trick to referencing a C global variable is to make a module, let's say foo.d: ------------------- extern (C) int x; ------------------- And then in your code: ----------------------- import foo; ... and then refer to foo.x ... ----------------------- but do NOT link in foo.obj. You'll find this trick is used in std.c.stdio to refer to _iob[]. stdio.obj is NOT added to phobos.lib, and so the linker will look elsewhere for a definition of _iob[].
Apr 25 2004
next sibling parent reply "Achilleas Margaritis" <axilmar in.gr> writes:
 The problem is that, in D, a declaration is a definition. So

     int x;

 will declare and define x. The trick to referencing a C global variable is
 to make a module, let's say foo.d:
 -------------------
 extern (C) int x;
 -------------------

 And then in your code:
 -----------------------
 import foo;

 ... and then refer to foo.x ...
 -----------------------

 but do NOT link in foo.obj. You'll find this trick is used in std.c.stdio

 refer to _iob[]. stdio.obj is NOT added to phobos.lib, and so the linker
 will look elsewhere for a definition of _iob[].

Thanks a lot. I will follow a better approach, in my opinion: provide a 2nd dll with getters/setters, and be consistent as to not having global variables, which is a bad idea anyway. Shouldn't you consider D not 'defining' external variables ? Programmers will get confused (as I have).
Apr 25 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6hed4$cga$1 digitaldaemon.com...
 Shouldn't you consider D not 'defining' external variables ? Programmers
 will get confused (as I have).

I considered that for a while. But the situation seemed to come up so rarely, and there was a reasonable workaround, and since exporting variables is generally considered a bad idea anyway, that I decided to leave it as is.
Apr 25 2004
parent reply Achilleas Margaritis <Achilleas_member pathlink.com> writes:
In article <c6hk8t$m3o$1 digitaldaemon.com>, Walter says...
"Achilleas Margaritis" <axilmar in.gr> wrote in message
news:c6hed4$cga$1 digitaldaemon.com...
 Shouldn't you consider D not 'defining' external variables ? Programmers
 will get confused (as I have).

I considered that for a while. But the situation seemed to come up so rarely, and there was a reasonable workaround, and since exporting variables is generally considered a bad idea anyway, that I decided to leave it as is.

Then what is the meaning for 'extern (C) <variable>' ?
Apr 26 2004
parent "Walter" <newshound digitalmars.com> writes:
"Achilleas Margaritis" <Achilleas_member pathlink.com> wrote in message
news:c6ilbf$2btp$1 digitaldaemon.com...
 Then what is the meaning for 'extern (C) <variable>' ?

extern (C) can be applied to any declaration, and means that it will have "C" name mangling and "C" calling conventions (for functions).
Apr 26 2004
prev sibling next sibling parent reply John Reimer <brk_6502 NOSP_AM.yahoo.com> writes:
Walter wrote:

 The problem is that, in D, a declaration is a definition. So
 
     int x;
 
 will declare and define x. The trick to referencing a C global variable is
 to make a module, let's say foo.d:
 -------------------
 extern (C) int x;
 -------------------
 
 And then in your code:
 -----------------------
 import foo;
 
 ... and then refer to foo.x ...
 -----------------------
 
 but do NOT link in foo.obj. You'll find this trick is used in std.c.stdio to
 refer to _iob[]. stdio.obj is NOT added to phobos.lib, and so the linker
 will look elsewhere for a definition of _iob[].
 
 

Good to know that this is possible! I was wondering how this was done. A couple of weeks ago, I ran into troubles trying to find a way to access the global errno variable (supposed to be accessible for determining the last error number) on Linux using D. It was easy enough to access functions like perror(), but all attempts to access the variable failed. It may be bad design at the system level, but apparently that's the way some things are done :-(.
Apr 25 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"John Reimer" <brk_6502 NOSP_AM.yahoo.com> wrote in message
news:c6i1jq$1ak7$1 digitaldaemon.com...
 Good to know that this is possible!  I was wondering how this was done.
   A couple of weeks ago, I ran into troubles trying to find a way to
 access the global errno variable (supposed to be accessible for
 determining the last error number) on Linux using D.  It was easy enough
 to access functions like perror(), but all attempts to access the
 variable failed.

There's std.c.linux.linux.getErrno() to get the linux errno value.
Apr 25 2004
parent John Reimer <brk_6502 yahoo.com> writes:
Walter wrote:

 
 There's std.c.linux.linux.getErrno() to get the linux errno value.
 
 

Ok... that's good to know. Thanks. -John
Apr 26 2004
prev sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
Wow, this is cool. And i stand corrected. :/ I wonder what made me think 
the variables exports don't work principally.

-eye

Walter schrieb:

 "Achilleas Margaritis" <axilmar in.gr> wrote in message
 news:c6gejo$1r7v$1 digitaldaemon.com...
 
Which means that I can't access a C global variable from D; the function

is
accessed ok, but the global variable is not.

Is this a bug ? is there some option that I should pass at the compiler ?

I am trying to port the Allegro multimedia library to D. Allegro functions
work ok, but Allegro global variables can't be accessed.

The problem is that, in D, a declaration is a definition. So int x; will declare and define x. The trick to referencing a C global variable is to make a module, let's say foo.d: ------------------- extern (C) int x; ------------------- And then in your code: ----------------------- import foo; ... and then refer to foo.x ... ----------------------- but do NOT link in foo.obj. You'll find this trick is used in std.c.stdio to refer to _iob[]. stdio.obj is NOT added to phobos.lib, and so the linker will look elsewhere for a definition of _iob[].

Apr 26 2004