digitalmars.D - extern(C) and data symbols
- Ben Hinkle (17/17) Jan 30 2005 Is there a way to get access to a data symbol defined in a C library? I'...
- Walter (6/21) Jan 30 2005 on
- Ben Hinkle (16/40) Jan 31 2005 ah. that worked. I was expecting "extern" to behave like it does in C/C+...
- Walter (15/28) Feb 01 2005 linkage-type
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (11/21) Feb 01 2005 One example of such an "exception" is libSDL, which uses macros in the
- Walter (5/7) Feb 01 2005 Yes. What you can do there is import a special "sdlextern.d" module into
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (9/15) Feb 01 2005 I'm not sure that would work in this case? Since there is no original
- Walter (5/19) Feb 01 2005 Put the functions that generate code into sdl.d. Put the 'extern'
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (19/32) Feb 02 2005 I'm not sure you follow me here...
- Ben Hinkle (5/7) Feb 01 2005 In my case it was macros defined by X11's header files that are just so
- Ben Hinkle (9/11) Feb 01 2005 I just bumped into another situation where I had to link in a translated...
- Walter (10/21) Feb 01 2005 in the
- Ben Hinkle (7/30) Feb 02 2005 The struct has two pointers. I noticed Anders is also missing his struct
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (3/6) Feb 02 2005 SDL_Event is a union declaration. No idea why it generates code...
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
Jan 30 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'monLinux 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 asmallC 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.
Jan 30 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...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. -BenIs there a way to get access to a data symbol defined in a C library? I'monLinux 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 asmallC 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.
Jan 31 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 alinkage-typeattribute. 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.
Feb 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
Feb 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.
Feb 01 2005
Walter wrote: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. --andersSome 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.
Feb 01 2005
"Anders F Björklund" <afb algonet.se> wrote in message news:ctolf7$13ui$1 digitaldaemon.com...Walter wrote: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.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.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.
Feb 01 2005
Walter wrote:I'm not sure you follow me here... I don't have a problem with external data symbols. I can see how that can be a problem with the surprise that "extern" works differently in D that what it does in C, but that's not the issue here in this case. The thing is that there is code generated from the SDL wrapper, in this case "sdl/video.d". And I am not including that on the compiler commandline, since I'm only compiling my own program that imports it. And when I link it, it's missing the macros-now-turned-functions: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./usr/bin/ld: Undefined symbols: _SDL_BlitSurface __D3sdl4main19SDL_InitApplicationFAAaZi __init_6events9SDL_EventWhile I *could* include the D module source code directly, "sdl/video.d sdl/events.d sdl/main.d", I prefer to compile those into a library, libSDL_d.a - and then include that. Either way, the D wrapper needs some extra code that C doesn't, because C uses the macro preprocessor instead of real functions. Nothing surprising about that, but it's a (tiny) hurdle to porting. But usually you can get away with just "extern(C)", const and alias. And neither of those generate any code, the problem is the macros... And like I said earlier, in this case it's due to the library design. --anders
Feb 02 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
Feb 01 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.
Feb 01 2005
"Ben Hinkle" <Ben_member pathlink.com> wrote in message news:ctph9f$1utc$1 digitaldaemon.com...in the1) 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 linkmodule since otherwise the linker can't find any initialization values forthestruct. Since that stuff isn't part of the C library it has to come fromD. That should only be necessary if the struct has non-zero initializers.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 theyhavefunction and variable declarations in one file and data structures andmacros inanother. Compared to the C header it seems less ideal.You don't need to put the functions and variables in a separate file. Just the variables.
Feb 01 2005
In article <ctpnrj$257m$2 digitaldaemon.com>, Walter says..."Ben Hinkle" <Ben_member pathlink.com> wrote in message news:ctph9f$1utc$1 digitaldaemon.com...The struct has two pointers. I noticed Anders is also missing his struct initializer __init_6events9SDL_Event. Maybe it's a Linux-only problem since I'm on Linux, too.in the1) 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 linkmodule since otherwise the linker can't find any initialization values forthestruct. Since that stuff isn't part of the C library it has to come fromD. That should only be necessary if the struct has non-zero initializers.You're right - it's not as bad as I thought. I now just have one file with the variables (and don't link it in) and the other file has everything else (and link it in).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 theyhavefunction and variable declarations in one file and data structures andmacros inanother. Compared to the C header it seems less ideal.You don't need to put the functions and variables in a separate file. Just the variables.
Feb 02 2005
Ben Hinkle wrote:The struct has two pointers. I noticed Anders is also missing his struct initializer __init_6events9SDL_Event. Maybe it's a Linux-only problem since I'm on Linux, too.SDL_Event is a union declaration. No idea why it generates code... --anders
Feb 02 2005