Jump to page: 1 2
Thread overview
gdc and gcc object linking issues
Jun 06, 2012
Andrej Mitrovic
Jun 06, 2012
Dmitry Olshansky
Jun 06, 2012
Dmitry Olshansky
Jun 06, 2012
Andrej Mitrovic
Jun 07, 2012
Kagamin
Jun 07, 2012
Andrej Mitrovic
Jun 07, 2012
Regan Heath
Jun 07, 2012
Kagamin
Jun 07, 2012
Dmitry Olshansky
Jun 07, 2012
Kagamin
Jun 07, 2012
Andrej Mitrovic
Jun 08, 2012
Kagamin
Jun 08, 2012
Andrej Mitrovic
June 06, 2012
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?
June 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
June 06, 2012
On 06.06.2012 22:39, Dmitry Olshansky wrote:
> 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;

int Class::statField; obviously



-- 
Dmitry Olshansky
June 06, 2012
On 6/6/12, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:
>> 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

Thanks, that fixed it! :)

Yeah C++ is a weirdo.
June 07, 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.
June 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.
June 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:
>> 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.

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/
June 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.
June 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.
June 07, 2012
On 07.06.2012 23:04, Kagamin wrote:
> 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++.

Indeed you can. Kind of anti-pattern.

> 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
« First   ‹ Prev
1 2