www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Clarification needed on export/extern

reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
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? 
Feb 21 2005
next sibling parent reply John Demme <me teqdruid.com> writes:
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? 
 
 

Feb 21 2005
parent Derek Parnell <derek psych.ward> writes:
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
Feb 21 2005
prev sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
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. 
Feb 24 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"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.
Feb 24 2005
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
Thanks!  That did the trick.  Now I just have to deal with a memory access 
violation in another, unrelated function :P 
Feb 24 2005