Irritating shortcoming with modules and externs

Derek Parnell derek at psych.ward
Tue May 16 17:26:41 PDT 2006


On Tue, 16 May 2006 18:22:40 -0400, Jarrett Billingsley wrote:

> Maybe it's not so much a shortcoming as it is just dumb.
> 
> Say I want to create a library which has a "pluggable function."  By that I 
> mean that I want the library to reference an external function, defined by 
> the user of the library.  So, in my library module, I write:
> 
> module mod;
> 
> extern(D) int intFunc();
> 
> void spork()
> {
>     for(int x = intFunc(); x != 0; x = intFunc())
>         writefln(x);
> }
> 
> Something purposeless, but it shows that I want to be able to use this 
> function within this module.
> 
> So I compile this to an obj/lib, and create my "host" program which uses the 
> library.  I have this:
> 
> module main;
> 
> import mod;
> 
> int intFunc()
> {
>     static int[5] ints = [4, 3, 2, 1, 0];
>     static int counter = 0;
> 
>     counter = (counter + 1) % 5;
>     return ints[counter];
> }
> 
> void main()
> {
>     spork();
> }
> 
> The problem: even though I've defined my intFunc() to match the signature to 
> be the same as the signature expected by the library, the linker won't 
> resolve the reference because the function names are mangled with the module 
> names as well.  Meaning that the linker is looking for mod.intFunc, but I've 
> given it main.intFunc.  So I limit the ability to use the library by 
> dictating that the user define the intFunc in a certain module (and it gets 
> worse when multiple source levels come up).
> 
> One workaround is to put "extern(C)" before the reference in the library and 
> before the definition, but I don't know if that interferes with the 
> exception handling stuff.
> 
> I doubt there's any robust solution to this, but it's frustrating 
> nonetheless.  

I've hit this limitation a few times too. The method I've used to get
around it (which might actually be the D-way) is to isolate the "pluggable"
function in its own module.

// --------- mod.d --------
module mod;
import std.stdio;
import oth;
void spork()
{
    for(int x = oth.intFunc(); x != 0; x = oth.intFunc())
        writefln(x);
}
//  -------- end mod.d -----------

// ---------- oth_r.d  ------------
// This is the source code for the library object.
module oth;
int intFunc()
{
    static int[5] ints = [4, 3, 2, 1, 0];
    static int counter = 0;

    counter = (counter + 1) % 5;
    return ints[counter];
}

// --------end of oth_r.d -----------

// ---------- oth_h.d  ------------
// This is the 'header' file for the library object.
module oth;
int intFunc();
// --------end of oth_h.d -----------

// -------- main. d ----------
module main;
import mod;
void main()
{
    mod.spork();
}
// ------- end of main.d -----------


To compile these, first I created the library...

 > copy oth_r.d oth.d /Y
 > build oth -full -Tmylib.lib

Then I created the executable ...

 > copy oth_h.d oth.d /Y
 > build main -full mylib.lib

Then I ran it ...

 >main
  3
  2
  1


-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
17/05/2006 10:14:19 AM



More information about the Digitalmars-d-learn mailing list