Thread overview
proper use of extern and export?
Jan 21, 2006
tyro[a.c.edwards]
Jan 21, 2006
Carlos Santander
January 21, 2006
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


January 21, 2006
"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.


January 21, 2006
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