www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - proper use of extern and export?

reply tyro[a.c.edwards] <tyro[a.c.edwards]_member pathlink.com> writes:
I have completely botched the original question so let me try a different
approach. In D, if I want to access a function defined in C all I need to do is
provide the function declaration as such:

#  extern (C) int system ( char* command );
#  void main() {
#   system("rids");
#  }

and viola, my program compiles an runs: no problems whatsoever. As you can see I
did not import any library module so why does this work? How can I do the same
with a function defined in another D module that is not included in Phoebos?

I was reading Thinking in C++ and came across this example:

#  //: C03:Global.cpp
#  //{L} Global2
#  // Demonstration of global variables
#  #include <iostream>
#  using namespace std;
#  
#  int globe;
#  void func();
#  int main() {
#    globe = 12;
#    cout << globe << endl;
#    func(); // Modifies globe
#    cout << globe << endl;
#  } ///:~
#  
#  //: C03:Global2.cpp {O}
#  // Accessing external global variables
#  extern int globe;  
#  // (The linker resolves the reference)
#  void func() {
#    globe = 47;
#  } ///:~

The book notes that this cannot be compiled to create an executable. So how do I
link the to files to create the executable? Since I don't program in C++ and am
only using the book because there's nothing available for D, I am trying all
examples in D. Hence my attempt here:

# --------- test.d ----------
# 
# import std.cstream;
# //import std.process;
# 
# int global;
# extern (D) void func();
# 
# void main() {
#   global = 12;
#   dout.writefln(global);
#   func();
#   dout.writefln(global);
# }
# 
# 
# --------- test2.d ----------
# 
# extern (D) int global;
# 
# void func() {
#   global = 47;
# }

I have tried defining func() as such:

# export void func() {
#   global = 47;
# }

but that doesn't work either.

I do understand the concept of importing modules but this is not my intent. I am
basically attempting to learn two thing: 1) How do I define a function in one
module and make it available to some other program or process (or from a
different language for that matter) without having to import that module? 2)
What exactly is the meaning of "export" and how exactly would it be used?

Thank you,
Andrew 
Jan 20 2006
next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"tyro[a.c.edwards]" <tyro[a.c.edwards]_member pathlink.com> wrote in message 
news:dqsfbk$htj$1 digitaldaemon.com...
 As you can see I
 did not import any library module so why does this work?

Because the "extern(C) int system(char* command);" tells the linker to look for a C function called system, which it finds in the CRT which is implicitly linked into your D programs.
 1) How do I define a function in one
 module and make it available to some other program or process (or from a
 different language for that matter) without having to import that module?

Do you know about object files, static libraries, or dynamically-linked libraries? That's how. You can compile your module that has functions and variables that use the "extern(D) export" attributes. That makes an object file (or more than one, if you're compiling several modules, in which case you package all those object files into a single library using the lib tool). Then, you make an "import module," which is like a D header file. It contains variable and function declarations. You don't compile this module; you only import it. You also specify on the command line that you want to link in the object file or library. Here's an example: 1. Make your library that you want to have some exported functions. module mymod; // Surround entire module with extern(D) export extern(D) export { int global; void func() { global = 47; } } Compile this like so: dmd mymod You end up with a file called mymod.obj (or mymod.o on *nix systems). ----------------------------------------------------- 2. Create an "import module" for mymod. This _has_ to have the same name as the original module, or else the compiler will not mangle the symbols properly. module mymod; // Still surround the module with extern(D) export extern(D) export { int global; void func(); } ------------------------------------------------ 3. Write your program. Import the import module. Do not compile it. module dtest; import mymod; import std.stdio; void main() { global = 12; writefln(global); func(); writefln(global); } Compile with dmd dtest mymod.obj It runs, and prints 12 47
 2)
 What exactly is the meaning of "export" and how exactly would it be used?

From Language>Attributes in the D spec: " Export means that any code outside the executable can access the member. Export is analogous to exporting definitions from a DLL. " This isn't an entirely complete definition, as it also means that any code outside the module (not just the executable) can access the member.
Jan 21 2006
prev sibling parent Carlos Santander <csantander619 gmail.com> writes:
tyro[a.c.edwards] escribió:
 I have completely botched the original question so let me try a different
 approach. In D, if I want to access a function defined in C all I need to do is
 provide the function declaration as such:
 
 #  extern (C) int system ( char* command );
 #  void main() {
 #   system("rids");
 #  }
 
 and viola, my program compiles an runs: no problems whatsoever. As you can see
I
 did not import any library module so why does this work? How can I do the same
 with a function defined in another D module that is not included in Phoebos?
 
 I was reading Thinking in C++ and came across this example:
 
 #  //: C03:Global.cpp
 #  //{L} Global2
 #  // Demonstration of global variables
 #  #include <iostream>
 #  using namespace std;
 #  
 #  int globe;
 #  void func();
 #  int main() {
 #    globe = 12;
 #    cout << globe << endl;
 #    func(); // Modifies globe
 #    cout << globe << endl;
 #  } ///:~
 #  
 #  //: C03:Global2.cpp {O}
 #  // Accessing external global variables
 #  extern int globe;  
 #  // (The linker resolves the reference)
 #  void func() {
 #    globe = 47;
 #  } ///:~
 
 The book notes that this cannot be compiled to create an executable. So how do
I
 link the to files to create the executable? Since I don't program in C++ and am
 only using the book because there's nothing available for D, I am trying all
 examples in D. Hence my attempt here:
 
 # --------- test.d ----------
 # 
 # import std.cstream;
 # //import std.process;
 # 
 # int global;
 # extern (D) void func();
 # 
 # void main() {
 #   global = 12;
 #   dout.writefln(global);
 #   func();
 #   dout.writefln(global);
 # }
 # 
 # 
 # --------- test2.d ----------
 # 
 # extern (D) int global;
 # 
 # void func() {
 #   global = 47;
 # }
 
 I have tried defining func() as such:
 
 # export void func() {
 #   global = 47;
 # }
 
 but that doesn't work either.
 
 I do understand the concept of importing modules but this is not my intent. I
am
 basically attempting to learn two thing: 1) How do I define a function in one
 module and make it available to some other program or process (or from a
 different language for that matter) without having to import that module? 2)
 What exactly is the meaning of "export" and how exactly would it be used?
 
 Thank you,
 Andrew 
 
 

Name mangling is your problem. In C (and I think C++ too) functions are mangled just with the name. In D, they're mangled with the module name. So, when you say in test.d: extern (D) void func(); The linker is looking for "test.func", but you only gave it "test2.func". If what you want is not import the whole of test2.d, write an import module with the same name, but in another directory, and import that one: // test2.d void func(); The same applies to the variable "test.global". -- Carlos Santander Bernal
Jan 21 2006