digitalmars.D.learn - gdc and gcc object linking issues
- Andrej Mitrovic (57/57) Jun 06 2012 This is a bit more related to C++ than D, it has to do with wrapping.
- Dmitry Olshansky (10/19) Jun 06 2012 Old boring C++ :)
- Dmitry Olshansky (4/19) Jun 06 2012 int Class::statField; obviously
- Andrej Mitrovic (3/10) Jun 06 2012 Thanks, that fixed it! :)
- Kagamin (14/14) Jun 07 2012 A class declaration is simply a declaration, it doesn't allocate
- Andrej Mitrovic (5/9) Jun 07 2012 This wasn't a collision error, it was a missing symbol error. The
- Regan Heath (9/18) Jun 07 2012 I don't think he was posting a solution to the OP, he was just describin...
- Kagamin (5/8) Jun 07 2012 I'm pretty sure you can define (with storage) global variable in
- Dmitry Olshansky (6/15) Jun 07 2012 Some libraries actually count on something like this, but I can't
- Kagamin (9/16) Jun 07 2012 You didn't define the variable. It doesn't matter in which
- Andrej Mitrovic (11/12) Jun 07 2012 Aah, I see what's going on. See, I was using this in the context of
- Kagamin (8/12) Jun 08 2012 Well, I'm not a C++ pro, but I won't recommend to place
- Andrej Mitrovic (4/11) Jun 08 2012 Yeah I thought they might appear in an existing library in a header
This is a bit more related to C++ than D, it has to do with wrapping. I've got 4 files: test.h: class Class { public: static int statField; }; test.cpp: #include "test.h" extern "C" __attribute__((dllexport)) int getStatField() { return Class::statField; } test.d: extern(C) int getStatField(); class Class { static int statField() { return getStatField(); } } main.d: import test; void main() { int x = Class.statField(); } This is how I compile it (XP32): g++ -m32 -g -I. -c test.cpp -o test_cpp.o gdc -m32 -g -I. -c test.d -o test_d.o gdc -m32 -g -I. -o main.exe test_cpp.o test_d.o main.d -lstdc++ But I get a linker error: test_cpp.o: In function `getStatField': D:\dev\code\d_code\testcpplink/test.cpp:5: undefined reference to `Class::statField' collect2: ld returned 1 exit status If I change the static int field to a static function (and add parenthesis for the function call) the linking works fine, e.g.: test.h: class Class { public: // was: static int statField; static int statField() { return 1; } }; test.cpp: #include "test.h" extern "C" __attribute__((dllexport)) int getStatField() { // was: return Class::statField; return Class::statField(); } But for variables it doesn't link. What am I doing wrong?
Jun 06 2012
On 06.06.2012 22:20, Andrej Mitrovic wrote:This is a bit more related to C++ than D, it has to do with wrapping. I've got 4 files: test.h: class Class { public: static int statField; };Old boring C++ :) Once you have this definition due to moronic linkage model (and probably some other reasonable things) you have to have: int Class:statField; declared somewhere in you cpp files that you link together so that compiler knows where to put it (in terms of obj files).But for variables it doesn't link. What am I doing wrong?Nothing, C++ is pile of dirt. :) -- Dmitry Olshansky
Jun 06 2012
On 06.06.2012 22:39, Dmitry Olshansky wrote:On 06.06.2012 22:20, Andrej Mitrovic wrote:int Class::statField; obviously -- Dmitry OlshanskyThis is a bit more related to C++ than D, it has to do with wrapping. I've got 4 files: test.h: class Class { public: static int statField; };Old boring C++ :) Once you have this definition due to moronic linkage model (and probably some other reasonable things) you have to have: int Class:statField;
Jun 06 2012
On 6/6/12, Dmitry Olshansky <dmitry.olsh gmail.com> wrote:Thanks, that fixed it! :) Yeah C++ is a weirdo.Old boring C++ :) Once you have this definition due to moronic linkage model (and probably some other reasonable things) you have to have: int Class:statField;int Class::statField; obviously
Jun 06 2012
A class declaration is simply a declaration, it doesn't allocate storage, so members end up being implicitly extern (or static inline for methods with bodies) except for instance fields, whose storage is allocated with the new operator. As static inlining a field has no sense, it becomes extern. You can declare extern variables in C too (try it). Extern declarations are included into each including module, but you can't do it with the variable's storage itself, so you should *define* the variable in a module where it will actually keep its value. If you define a variable in the header, it will be included in each including module and you'll get several instances of the variable and symbol collision at link time. You can think of a class as an interface declaration which happens to expose some implementation details to you.
Jun 07 2012
On 6/7/12, Kagamin <spam here.lot> wrote:If you define a variable in the header, it will be included in each including module and you'll get several instances of the variable and symbol collision at link time.This wasn't a collision error, it was a missing symbol error. The variable is static, so it should be in the data or bss segment. You seem to be talking about instance variables but that wasn't the issue here.
Jun 07 2012
On Thu, 07 Jun 2012 15:12:46 +0100, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 6/7/12, Kagamin <spam here.lot> wrote:I don't think he was posting a solution to the OP, he was just describing some background :) In the quoted passage above I suspect he was referring to a static/global variable defined in a C header, not a C++ class member static or otherwise. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/If you define a variable in the header, it will be included in each including module and you'll get several instances of the variable and symbol collision at link time.This wasn't a collision error, it was a missing symbol error. The variable is static, so it should be in the data or bss segment. You seem to be talking about instance variables but that wasn't the issue here.
Jun 07 2012
On Thursday, 7 June 2012 at 14:29:24 UTC, Regan Heath wrote:In the quoted passage above I suspect he was referring to a static/global variable defined in a C header, not a C++ class member static or otherwise.I'm pretty sure you can define (with storage) global variable in header file both in C and C++. But don't qualify it static in C: this will make it hidden symbol so you will have several instances of the variable but no symbol collision.
Jun 07 2012
On 07.06.2012 23:04, Kagamin wrote:On Thursday, 7 June 2012 at 14:29:24 UTC, Regan Heath wrote:Indeed you can. Kind of anti-pattern.In the quoted passage above I suspect he was referring to a static/global variable defined in a C header, not a C++ class member static or otherwise.I'm pretty sure you can define (with storage) global variable in header file both in C and C++.But don't qualify it static in C: this will make it hidden symbol so you will have several instances of the variable but no symbol collision.Some libraries actually count on something like this, but I can't remember offhand. Logging probably? -- Dmitry Olshansky
Jun 07 2012
On Thursday, 7 June 2012 at 14:12:56 UTC, Andrej Mitrovic wrote:This wasn't a collision error, it was a missing symbol error. The variable is static, so it should be in the data or bss segment. You seem to be talking about instance variables but that wasn't the issue here.You didn't define the variable. It doesn't matter in which section a variable is placed, but which module it's defined in. In D you have declarations in .di files, but .di files alone won't work as you won't have the declared variables' storage - you'll have to link to an object compiled from the corresponding .d file because .d has definitions and that's how actual D members *definitions* are compiled and their storage allocated in sections.
Jun 07 2012
On 6/7/12, Kagamin <spam here.lot> wrote:You didn't define the variable.Aah, I see what's going on. See, I was using this in the context of wrapping existing C++ libs. Since I was writing a small test-case for wrapping a static field I made a header file with a static field declaration but no .cpp implementation files (except the wrapper). I didn't know I had to either have an initializer in the header or have a .cpp file with the definition. For actual C++ libs the definition of a static field is somewhere in an existing cpp file, so I don't have to re-define the static field when wrapping (otherwise I'd probably get collisions or multiple independent variables).
Jun 07 2012
On Thursday, 7 June 2012 at 23:58:21 UTC, Andrej Mitrovic wrote:I didn't know I had to either have an initializer in the header or have a .cpp file with the definition.Well, I'm not a C++ pro, but I won't recommend to place initializer in the header. That sounds odd. What would it mean? I guess, it will mean definition, so chances are it's not what you want. Initializers belong to definitions, and definitions belong to .cpp, that's how it usually works unless you know for sure you want something else. Bindings are just fine with declarations alone + support code.
Jun 08 2012
On 6/8/12, Kagamin <spam here.lot> wrote:Well, I'm not a C++ pro, but I won't recommend to place initializer in the header. That sounds odd. What would it mean? I guess, it will mean definition, so chances are it's not what you want. Initializers belong to definitions, and definitions belong to .cpp, that's how it usually works unless you know for sure you want something else. Bindings are just fine with declarations alone + support code.Yeah I thought they might appear in an existing library in a header file but it seems they're in the definition file. Thanks for your help.
Jun 08 2012