Thread overview
Clarification needed on export/extern
Feb 22, 2005
John Demme
Feb 22, 2005
Derek Parnell
Feb 24, 2005
Ben Hinkle
February 22, 2005
I've been having some trouble accessing an exported struct in a premade lib using the extern keyword, so I tried to recreate the problem I was having, and now I'm kind of stuck.  I think I'm just not understanding something correctly.

Here's where I am now:


1) I have a file called exporter.d that contains the following code:

struct A
{
    int x,y;
}

static export A a={5,10};

I compile this to an .obj file.  All is well.


2) I have a file called main.d that contains the following code.

import std.stdio;

struct A
{
    int x,y;
}

extern A a;

void main()
{
    writefln(a.x);
}

This program is compiled with the exporter.obj file.


Now: it gives me a linker error saying that it can't find _D4main1aS4main1A, which means it's looking for the symbol named "a" in "main" with a type of "main.A."  Oookay, I'd really love for it to look for that symbol in another file, namely exporter.obj.  I thought that's why I put "extern" in front of "A a."

If I change my extern line to something like "extern(D) A a" or "extern(Windows) A a" or even "extern() A a," it compiles, links, and runs, but prints 0.  It's obviously not linking to the external symbol.

How on earth do I get it to look in exporter.obj for "a"?  I've run exporter.obj through libunres and it is in fact exporting its "a," although it's called "_D8exporter1aS8exporter1A."  I've tried using a .def file with an IMPORTS directive to translate the names, but all it does is give me some horrendous linker error about an illegal frame on a start address, and.. I don't need that kind of drama.

What am I missing?


February 22, 2005
exporter.d:
module exporter;

struct A
{
	int x,y;
}

A a = {5,10};

main.d:
module main;
import exporter;
import std.stdio;

void main() {
	writefln(a.x);
}

D is not C... not even close.

John

Jarrett Billingsley wrote:
> I've been having some trouble accessing an exported struct in a premade lib using the extern keyword, so I tried to recreate the problem I was having, and now I'm kind of stuck.  I think I'm just not understanding something correctly.
> 
> Here's where I am now:
> 
> 
> 1) I have a file called exporter.d that contains the following code:
> 
> struct A
> {
>     int x,y;
> }
> 
> static export A a={5,10};
> 
> I compile this to an .obj file.  All is well.
> 
> 
> 2) I have a file called main.d that contains the following code.
> 
> import std.stdio;
> 
> struct A
> {
>     int x,y;
> }
> 
> extern A a;
> 
> void main()
> {
>     writefln(a.x);
> }
> 
> This program is compiled with the exporter.obj file.
> 
> 
> Now: it gives me a linker error saying that it can't find _D4main1aS4main1A, which means it's looking for the symbol named "a" in "main" with a type of "main.A."  Oookay, I'd really love for it to look for that symbol in another file, namely exporter.obj.  I thought that's why I put "extern" in front of "A a."
> 
> If I change my extern line to something like "extern(D) A a" or "extern(Windows) A a" or even "extern() A a," it compiles, links, and runs, but prints 0.  It's obviously not linking to the external symbol.
> 
> How on earth do I get it to look in exporter.obj for "a"?  I've run exporter.obj through libunres and it is in fact exporting its "a," although it's called "_D8exporter1aS8exporter1A."  I've tried using a .def file with an IMPORTS directive to translate the names, but all it does is give me some horrendous linker error about an illegal frame on a start address, and.. I don't need that kind of drama.
> 
> What am I missing? 
> 
> 
February 22, 2005
On Tue, 22 Feb 2005 00:39:30 -0500, John Demme wrote:

> exporter.d:
> module exporter;
> 
> struct A
> {
> 	int x,y;
> }
> 
> A a = {5,10};
> 
> main.d:
> module main;
> import exporter;
> import std.stdio;
> 
> void main() {
> 	writefln(a.x);
> }
> 
> D is not C... not even close.
> 
> John
> 
> Jarrett Billingsley wrote:
>> I've been having some trouble accessing an exported struct in a premade lib using the extern keyword, so I tried to recreate the problem I was having, and now I'm kind of stuck.  I think I'm just not understanding something correctly.
>> 
>> Here's where I am now:
>> 
>> 1) I have a file called exporter.d that contains the following code:
>> 
>> struct A
>> {
>>     int x,y;
>> }
>> 
>> static export A a={5,10};
>> 
>> I compile this to an .obj file.  All is well.
>> 
>> 2) I have a file called main.d that contains the following code.
>> 
>> import std.stdio;
>> 
>> struct A
>> {
>>     int x,y;
>> }
>> 
>> extern A a;
>> 
>> void main()
>> {
>>     writefln(a.x);
>> }
>> 
>> This program is compiled with the exporter.obj file.
>> 
>> Now: it gives me a linker error saying that it can't find _D4main1aS4main1A, which means it's looking for the symbol named "a" in "main" with a type of "main.A."  Oookay, I'd really love for it to look for that symbol in another file, namely exporter.obj.  I thought that's why I put "extern" in front of "A a."
>> 
>> If I change my extern line to something like "extern(D) A a" or "extern(Windows) A a" or even "extern() A a," it compiles, links, and runs, but prints 0.  It's obviously not linking to the external symbol.
>> 
>> How on earth do I get it to look in exporter.obj for "a"?  I've run exporter.obj through libunres and it is in fact exporting its "a," although it's called "_D8exporter1aS8exporter1A."  I've tried using a .def file with an IMPORTS directive to translate the names, but all it does is give me some horrendous linker error about an illegal frame on a start address, and.. I don't need that kind of drama.
>> 
>> What am I missing?
>> 
>>

By putting the struct definition into main.d, when you define "extern A a;" it tells the linker to look for the 'a' inside a module called 'main' rather than 'exporter'. Because the struct was also defined and the 'a' was defined i the 'exporter' module, that is what it is known as in the obj file - namely as 'exporter.a'.

To simplify matters, D does away with a lot of these linkage hassles. Create the exporter.d file as you have (but it doesn't need the "export" keyword). Then make your main.d file look like this ...

 import std.stdio;
 import exporter;

 void main()
 {
     writefln(a.x);
 }

I tested this and this is the result I got ...

C:\temp>dmd exporter.d -c

C:\temp>dmd main.d -c

C:\temp>dmd main.obj exporter.obj C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe main+exporter,,,user32+kernel32/noi;

C:\temp>main
5

Of course, I also used a simpler way too ...

C:\temp>build main
C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe
main+exporter,main.exe,,user32+kernel3
2/noi;

C:\temp>main
5

Hope this helps.

-- 
Derek
Melbourne, Australia
22/02/2005 4:49:35 PM
February 24, 2005
The problem is that this struct is defined in a lib that was compiled with C linkage.  I need to access this struct.  I can't figure out how.


February 24, 2005
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message news:cvlhce$21rt$1@digitaldaemon.com...
> The problem is that this struct is defined in a lib that was compiled with C linkage.  I need to access this struct.  I can't figure out how.

I think this has come up a couple times recently. Here's what you should do:
write a d file that has the definition of the struct but don't link it in.
For example, say foo.lib has the struct Bar in it then write
foo.d
  extern (C):
  struct BarType {
    int x;
    int y;
  }
  BarType Bar;

then import foo into your regular d code:

main.d
  import foo;
  int main() {
    printf("Bar.x is %d\n",Bar.x);
    return 0;
  }

Now the key is that you don't link in foo.obj:
  dmd -c main.d
  dmd main.obj foo.lib

Or if you use the nifty "build" utility you can tell it to do all that for you.


February 25, 2005
Thanks!  That did the trick.  Now I just have to deal with a memory access violation in another, unrelated function :P