Jump to page: 1 2
Thread overview
extern(C) and data symbols
Jan 31, 2005
Ben Hinkle
Jan 31, 2005
Walter
Feb 01, 2005
Ben Hinkle
Feb 01, 2005
Walter
Feb 01, 2005
Walter
Feb 02, 2005
Walter
Feb 01, 2005
Ben Hinkle
Feb 02, 2005
Ben Hinkle
Feb 02, 2005
Walter
Feb 02, 2005
Ben Hinkle
January 31, 2005
Is there a way to get access to a data symbol defined in a C library? I'm on
Linux and I've tried
  extern (C) int foo;
or
  export int foo;
but I can't seem to get ahold of the symbol. The linker complains I'm
changing the definition. So for now my only workaround is to define a small
C file with

extern int foo;
int getFoo() {
 return foo;
}

and then put
  extern (C) int getFoo();
in my D code and call that whenever I need foo. Is there a better way?

thanks,
-Ben


January 31, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:ctk9og$ch7$1@digitaldaemon.com...
> Is there a way to get access to a data symbol defined in a C library? I'm
on
> Linux and I've tried
>   extern (C) int foo;
> or
>   export int foo;
> but I can't seem to get ahold of the symbol. The linker complains I'm
> changing the definition. So for now my only workaround is to define a
small
> C file with
>
> extern int foo;
> int getFoo() {
>  return foo;
> }
>
> and then put
>   extern (C) int getFoo();
> in my D code and call that whenever I need foo. Is there a better way?

Sure. Declare it in a D module, then do not link in that module. That's how std.c.stdio works for the globals stdin, stdout, etc.


February 01, 2005
"Walter" <newshound@digitalmars.com> wrote in message news:ctko8r$1noa$1@digitaldaemon.com...
>
> "Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:ctk9og$ch7$1@digitaldaemon.com...
>> Is there a way to get access to a data symbol defined in a C library? I'm
> on
>> Linux and I've tried
>>   extern (C) int foo;
>> or
>>   export int foo;
>> but I can't seem to get ahold of the symbol. The linker complains I'm
>> changing the definition. So for now my only workaround is to define a
> small
>> C file with
>>
>> extern int foo;
>> int getFoo() {
>>  return foo;
>> }
>>
>> and then put
>>   extern (C) int getFoo();
>> in my D code and call that whenever I need foo. Is there a better way?
>
> Sure. Declare it in a D module, then do not link in that module. That's
> how
> std.c.stdio works for the globals stdin, stdout, etc.
>

ah. that worked. I was expecting "extern" to behave like it does in C/C++
wrt data - ie it becomes a storage-class attribute instead of a linkage-type
attribute. That was why I tried various combinations of export as well. As
it stands I'm still going to have to have two files since my original file
had function definitions that I need to include in the link command and
these extern data declarations that I now need to exclude from the link
command. So it looks like at least I'll avoid having a C file in there but
still it seems too bad that
1) extern applied to data will confuse C/C++ programmers
2) there doesn't seem to be any way to say in the source file the D
equivalent to the C/C++ meaning.
It doesn't make me feel warm and fuzzy, but then there's a lot of snow
outside so maybe that has something to do with it.
-Ben


February 01, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:ctmnsr$27ae$1@digitaldaemon.com...
> ah. that worked. I was expecting "extern" to behave like it does in C/C++ wrt data - ie it becomes a storage-class attribute instead of a
linkage-type
> attribute. That was why I tried various combinations of export as well. As
> it stands I'm still going to have to have two files since my original file
> had function definitions that I need to include in the link command and
> these extern data declarations that I now need to exclude from the link
> command. So it looks like at least I'll avoid having a C file in there but
> still it seems too bad that
> 1) extern applied to data will confuse C/C++ programmers
> 2) there doesn't seem to be any way to say in the source file the D
> equivalent to the C/C++ meaning.
> It doesn't make me feel warm and fuzzy, but then there's a lot of snow
> outside so maybe that has something to do with it.

I ran into this issue a while back when creating std.c.stdio.d, and thought of the same issues. I decided to leave it as it is because:

1) Few C libraries attempt to use global variables as part of their API. It's also considered bad form to do it. Nevertheless, it does happen.

2) A D module that only serves as an interface to C code rarely has a need to define its own code, so it rarely needs to be linked in.

3) Combining 1) and 2) means the issue comes up only rarely. Therefore, I
thought it not worth the extra syntax it would need, especially since the
problem has an easy workaround (I should add it to the
www.digitalmars.com/techtips !)

A more troublesome issue was errno, which looks like a global but isn't. Arrgh.


February 01, 2005
Walter wrote:

> I ran into this issue a while back when creating std.c.stdio.d, and thought
> of the same issues. I decided to leave it as it is because:
> 
> 1) Few C libraries attempt to use global variables as part of their API.
> It's also considered bad form to do it. Nevertheless, it does happen.
> 
> 2) A D module that only serves as an interface to C code rarely has a need
> to define its own code, so it rarely needs to be linked in.

One example of such an "exception" is libSDL, which uses macros in the header files. At least for SDL_main, SDL_BlitSurface and SDL_LoadBMP...


Some can be covered with alias, but some require functions to replace the macros. And where there are functions, there is code. (and objects)

> /* Convenience macro -- load a surface from a file */
> #define SDL_LoadBMP(file)	SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)

Thus: libSDL_d.a and libSDLmain_d.a, with the D wrapper code.


But it's all SDL's fault. GLUT does the same thing, without any macros.
Which, incidentally, also makes it (GLUT) a lot easier to use from D...

And if someone says "but Windows and Linux doesn't need a custom
SDLmain" one more time, they're gonna get whacked upside da head :-)

--anders
February 01, 2005
> 2) A D module that only serves as an interface to C code rarely has a need to define its own code, so it rarely needs to be linked in.

In my case it was macros defined by X11's header files that are just so pervasive in C/C++ code that I translated them to D. So now I have a D file for the macros and a D file for the "pure" interface. It isn't unreasonable to keep those separate, though, so it isn't a disaster.

-Ben


February 01, 2005
"Anders F Björklund" <afb@algonet.se> wrote in message news:ctnkta$25r$1@digitaldaemon.com...
> Some can be covered with alias, but some require functions to replace the macros. And where there are functions, there is code. (and objects)

Yes. What you can do there is import a special "sdlextern.d" module into sdl.d so the user of the module never has to worry about it. Phobos does just this in std.c.linux.linux.


February 01, 2005
Walter wrote:

>>Some can be covered with alias, but some require functions to replace
>>the macros. And where there are functions, there is code. (and objects)
> 
> Yes. What you can do there is import a special "sdlextern.d" module into
> sdl.d so the user of the module never has to worry about it. Phobos does
> just this in std.c.linux.linux.

I'm not sure that would work in this case? Since there is no original code, the only thing that exists in the C libraries symbol exports is
"SDL_LoadBMP_RW" - the SDL_LoadBMP symbol is undefined (just a macro).

So in order to have a function to call, I need to implement it in D.
And when I do, I get object code for the function wrapper (D) code ?
And this code has to be linked in somehow, I used an extra library...

Hopefully, the function will be easy to inline in the release version.

--anders
February 02, 2005
"Anders F Björklund" <afb@algonet.se> wrote in message news:ctolf7$13ui$1@digitaldaemon.com...
> Walter wrote:
>
> >>Some can be covered with alias, but some require functions to replace the macros. And where there are functions, there is code. (and objects)
> >
> > Yes. What you can do there is import a special "sdlextern.d" module into sdl.d so the user of the module never has to worry about it. Phobos does just this in std.c.linux.linux.
>
> I'm not sure that would work in this case? Since there is no original code, the only thing that exists in the C libraries symbol exports is "SDL_LoadBMP_RW" - the SDL_LoadBMP symbol is undefined (just a macro).
>
> So in order to have a function to call, I need to implement it in D. And when I do, I get object code for the function wrapper (D) code ? And this code has to be linked in somehow, I used an extra library...
>
> Hopefully, the function will be easy to inline in the release version.

Put the functions that generate code into sdl.d. Put the 'extern' declarations in sdlextern.d. In sdl.d, import sdlextern.d, but do not link in sdlextern.obj. You can see this at work in std.c.linux.linux.


February 02, 2005
>1) Few C libraries attempt to use global variables as part of their API. It's also considered bad form to do it. Nevertheless, it does happen.

I just bumped into another situation where I had to link in a translated C header: _init_MyStruct in the data segment. In other words if the C header declares a struct and I put that definition in my D module I need to link in the module since otherwise the linker can't find any initialization values for the struct. Since that stuff isn't part of the C library it has to come from D.

So I have to add the struct definitions to the same file that has all the translated macros. It's getting header to read those modules since they have function and variable declarations in one file and data structures and macros in another. Compared to the C header it seems less ideal.


« First   ‹ Prev
1 2