www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Shared library extern (C) variables

reply "Mineko" <uminekorox gmail.com> writes:
I keep getting mixed results searching for this. :\

Just as the title says, is it safe to extern (C) variables?

Something like this:
extern (C) auto foo = 800;

And then call that from another program?

Also, just because this has been bugging me for a while.. Is 
export broken, or it it not supposed to be used the same way as 
extern (C)?
Jan 05 2014
next sibling parent reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
On Sunday, 5 January 2014 at 18:22:54 UTC, Mineko wrote:
 I keep getting mixed results searching for this. :\

 Just as the title says, is it safe to extern (C) variables?

 Something like this:
 extern (C) auto foo = 800;

 And then call that from another program?

 Also, just because this has been bugging me for a while.. Is 
 export broken, or it it not supposed to be used the same way as 
 extern (C)?
I wouldn't do it that way. I would use extern(C) with struct and function definitions/declarations, but I don't think it makes sense to use it with individual variables. Not sure if anything is wrong with export, but they are two different things. Export allows something to be visible to other programs(like in a shared library) and extern is(I believe) more so for specifying how something outside the program is meant to be linked in.
Jan 05 2014
parent "Mineko" <uminekorox gmail.com> writes:
On Sunday, 5 January 2014 at 19:08:44 UTC, Jeremy DeHaan wrote:
 On Sunday, 5 January 2014 at 18:22:54 UTC, Mineko wrote:
 I keep getting mixed results searching for this. :\

 Just as the title says, is it safe to extern (C) variables?

 Something like this:
 extern (C) auto foo = 800;

 And then call that from another program?

 Also, just because this has been bugging me for a while.. Is 
 export broken, or it it not supposed to be used the same way 
 as extern (C)?
I wouldn't do it that way. I would use extern(C) with struct and function definitions/declarations, but I don't think it makes sense to use it with individual variables. Not sure if anything is wrong with export, but they are two different things. Export allows something to be visible to other programs(like in a shared library) and extern is(I believe) more so for specifying how something outside the program is meant to be linked in.
My program is a shared library, and it uses extern (C) to let other programs access the extern (C)'d functions and such. Could you give me a definition of export, as I believe I may have the wrong meaning and use of it. The reason being, is that I did some test with something like this: export int test(string[] args) { return 0; } and the program trying to find it couldn't, I suppose that's where I went wrong? Back the main topic, thank you, I wanted to use it for variables, but if it's not safe I'll use getters and setters, or maybe ref or something. The reason I wanted to is because I'm using it as a sort of settings.
Jan 05 2014
prev sibling parent reply "FreeSlave" <freeslave93 gmail.com> writes:
On Sunday, 5 January 2014 at 18:22:54 UTC, Mineko wrote:
 I keep getting mixed results searching for this. :\

 Just as the title says, is it safe to extern (C) variables?

 Something like this:
 extern (C) auto foo = 800;

 And then call that from another program?

 Also, just because this has been bugging me for a while.. Is 
 export broken, or it it not supposed to be used the same way as 
 extern (C)?
Some code snippets of what you try to do would help. Maybe this example explain you something: //mod.d extern(C) int foo = 42; void changeFoo(int val) { foo = val; } //main.d import std.stdio; import mod; int main() { writeln(foo); changeFoo(15); writeln(foo); return 0; } Compile: dmd -H -c mod.d && //to generate .di file (not required) dmd -shared mod.d -oflibmod.so && //to generate shared library dmd -L-L. -L-lmod -L-rpath=. main.d //rpath is special argument to linker, so executable will able to find shared library in its directory. You can omit rpath, but then you must put your .so file to one of standard directory like /usr/lib or /usr/local/lib. That's all for Linux. On Windows you would have different building steps. Also probably you want to make your varialbe __gshared, so it will not be thread-local. That's default D behavior to make all global variables thread-local. And I don't know how other languages will handle D thread-local variable.
Jan 05 2014
parent reply "Mineko" <uminekorox gmail.com> writes:
On Sunday, 5 January 2014 at 19:47:46 UTC, FreeSlave wrote:
 Some code snippets of what you try to do would help.

 Maybe this example explain you something:

 //mod.d
 extern(C) int foo = 42;

 void changeFoo(int val)
 {
     foo = val;
 }

 //main.d
 import std.stdio;
 import mod;

 int main()
 {
     writeln(foo);
     changeFoo(15);
     writeln(foo);
     return 0;
 }

 Compile:
 dmd -H -c mod.d && //to generate .di file (not required)
 dmd -shared mod.d -oflibmod.so && //to generate shared library
 dmd -L-L. -L-lmod -L-rpath=. main.d //rpath is special argument 
 to linker, so executable will able to find shared library in 
 its directory. You can omit rpath, but then you must put your 
 .so file to one of standard directory like /usr/lib or 
 /usr/local/lib. That's all for Linux. On Windows you would have 
 different building steps.

 Also probably you want to make your varialbe __gshared, so it 
 will not be thread-local. That's default D behavior to make all 
 global variables thread-local. And I don't know how other 
 languages will handle D thread-local variable.
Ahh I appreciate it, but I already have that part down and good. :) I was wondering about how to use export correctly, I apologize for not being clear. Also I'll keep in mind the __gshared, never even knew about it.
Jan 05 2014
next sibling parent "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
On Sunday, 5 January 2014 at 19:55:50 UTC, Mineko wrote:
 On Sunday, 5 January 2014 at 19:47:46 UTC, FreeSlave wrote:
 Some code snippets of what you try to do would help.

 Maybe this example explain you something:

 //mod.d
 extern(C) int foo = 42;

 void changeFoo(int val)
 {
    foo = val;
 }

 //main.d
 import std.stdio;
 import mod;

 int main()
 {
    writeln(foo);
    changeFoo(15);
    writeln(foo);
    return 0;
 }

 Compile:
 dmd -H -c mod.d && //to generate .di file (not required)
 dmd -shared mod.d -oflibmod.so && //to generate shared library
 dmd -L-L. -L-lmod -L-rpath=. main.d //rpath is special 
 argument to linker, so executable will able to find shared 
 library in its directory. You can omit rpath, but then you 
 must put your .so file to one of standard directory like 
 /usr/lib or /usr/local/lib. That's all for Linux. On Windows 
 you would have different building steps.

 Also probably you want to make your varialbe __gshared, so it 
 will not be thread-local. That's default D behavior to make 
 all global variables thread-local. And I don't know how other 
 languages will handle D thread-local variable.
Ahh I appreciate it, but I already have that part down and good. :) I was wondering about how to use export correctly, I apologize for not being clear. Also I'll keep in mind the __gshared, never even knew about it.
Yeah, the documentation could definitely be better in this regard. I don't really have any experience when it comes to linking to D shared libraries. All my experience comes from linking with C ones. I might try it out later today just to make sure I have it right, but it should be something kind of like this: libstuff.d //extern(C) only added because that is what you have been doing export extern(C) void someFunction(int thing) { //doing stuff with the thing } extern(C) void otherFunction(int otherThing) { //stuff with a different thing } Assuming libstuff gets put into the shared library main.d import libstuff; void main(sring[] args) { int sweetVariable = 100; someFunction(sweetVariable);//should be ok otherFunction(sweetVariable);//error, not exported } Again, I cannot confirm that this is the exact way to do it, but it should be something very similar from what the documentation leads me to believe.
Jan 05 2014
prev sibling parent reply "TheFlyingFiddle" <kurtyan student.chalmers.se> writes:
On Sunday, 5 January 2014 at 19:55:50 UTC, Mineko wrote:
 Ahh I appreciate it, but I already have that part down and 
 good. :)

 I was wondering about how to use export correctly, I apologize 
 for not being clear.

 Also I'll keep in mind the __gshared, never even knew about it.
Export is currently somewhat broken see DIP45 for an indepth explanation (link) To be able to load symbols from libraries at runtime they have to be declared with extern. This rule does not hold on linux though since it simply makes all the symbols avalible but for other systems it is important. So for instance: void foo() { ... } //This will NOT be avalible for loading under windows. export void foo() { ... } //This is avalible for loading under windows. extern(C) void foo() { ... } //This will also not be avalible for loading. extern is a whole diffrent creature. extern deals with name mangling and calling conventions. extern(C) void foo() { ... } Uses C name mangling and calling convention: C name mangling is no name mangling so the symbol for foo() will simply be foo All symbols not annotated with an extern will automatically be extern(D) and wil use the standard D name mangling and calling convetion. D name mangling makes this: module main; void foo() { ... } into _D4main3fooFZv This is probably why you did not succeed in loading your test function. So to sum up: export deals with DLL/shared library symbol visibility. extern(C/D/Windows/C++/Pascal) deals with name mangling and calling convention.
Jan 05 2014
parent reply Jacob Carlborg <doob me.com> writes:
On 2014-01-05 22:15, TheFlyingFiddle wrote:

 Export is currently somewhat broken see DIP45 for an indepth explanation
 (link)

 To be able to load symbols from libraries at runtime they have to be
 declared with extern.
"export", not "extern".
 This rule does not hold on linux though since it
 simply makes all the symbols avalible but for other systems it is
 important.
On Posix, not just Linux. -- /Jacob Carlborg
Jan 06 2014
parent "TheFlyingFiddle" <kurtyan student.chalmers.se> writes:
On Monday, 6 January 2014 at 09:27:26 UTC, Jacob Carlborg wrote:
 To be able to load symbols from libraries at runtime they have 
 to be
 declared with extern.
"export", not "extern".
Yeah typo sry.
Jan 06 2014