Search code examples
dlladagnat

How do I link a custom dll in Ada?


So this is a simple project I put together just to test before doing some cool stuff with it later. The eventual goal is to make the program able to handle modularity through awesome dll kung fu.

But, baby steps. Right now I just want to make the thing link.

Here I have Adder.ads:

package Adder is

    function Add(A : Integer; B : Integer) return Integer;

end Adder;

And the respective Adder.adb:

package body Adder is

    function Add(A : Integer; B : Integer) return Integer is
    begin
        return A + B;
    end Add;

end Adder;

Exciting, I know.

I've seen several different tutorials on how to do this, and none of them agree, but taking a cue from this one, I came up with these commands:

gnatmake -c Adder.adb
gcc -shared -shared-libgcc -o Adder.dll Adder.o

This at least generates a dll. I dunno if it generates one that will actually work or if the problem is with the main exe though.

Now the main exe, I have kept everything in a separate directory so gnat doesn't try to cheat and use the .ali and .o files. Then you copy the dll into the directory before trying to build. I've tried this tweaking lots of different ways and gotten several different errors, but here is what I have right now.

Main.adb:

with Adder_Spec; use Adder_Spec;
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
begin
    Put_Line(Integer'Image(Add(3,4)));
end Main;

Yay most useless program ever. Now, knowing I'm supposed to have a spec for the dll, I came up with the aforewith'd Adder_Spec.ads:

package Adder_Spec is

    function Add(A : Integer; B : Integer) return Integer;

private

    pragma Import(Ada, Add, "Add");

end Adder_Spec;

Now, like I said I've tried this a bunch of different ways, sometimes omitting the third import parameter, other times omitting the import altogether, sometimes keeping the import but not separating it into the private part, you name it. I've also tried playing with the compile command several ways, but here's the most recent one:

gnatmake Main.adb -bargs -shared -largs -lAdder

With this particular command it spits out an "Undefined reference to 'Add'" error. If I add the -v flag, it doesn't provide much more useful information.

Checking gnatmake --help shows me that the default mode is gnat 2012, if that makes any difference. It probably shouldn't, as I've tried compiling with the flags for 2005 and 95, too.

So... can anybody savvy enough spot the problem? Thanks in advance.


Solution

  • If you want to say

    package Adder_Spec is
        function Add(A : Integer; B : Integer) return Integer;
    private
        pragma Import(Ada, Add, "Add");
    end Adder_Spec;
    

    when importing the DLL, then you have to say

    package Adder is
        function Add(A : Integer; B : Integer) return Integer;
        pragma Export (Ada, Add, "Add");
    end Adder;
    

    when building it.

    GNAT’s default linker name for the generated Add would be (I think) adder__add; you should be able to see what it is using nm Adder.o.