Search code examples
adagnat

undefined reference to 'do_varargs' with gnat


After the compilation, when I try to build my DLL with win32ada 2017 and GNAT 2017, it issues an error :

gnatlink <ali\file> -o <jnk\file> -mdll -Wl,base-file,<base\file>  
win32-winuser.o:win32-winuser.adb:(.text+0xa62): undefined reference to 'do_varargs'  
win32-winuser.o:win32-winuser.adb:(.text+0x15be): undefined reference to 'do_varargs'  
collect2.exe: error: ld returned 1 exit status  
gnatlink: error when calling C:\GNAT\2017\bin\gcc.exe

Do you know why gnatlink issues this error ?

Edit :

fichier pour la compilation situé dans un dossier :

@echo on

set GNAT_PATH=C:\GNAT\2017
set gnatbin=%GNAT_PATH%\bin
set winada=%GNAT_PATH%\lib\win32ada

set path=%gnatbin%;%path%;

set INTERFACE_DLL=..

set obj=%INTERFACE_DLL%\obj

set GCCARGS=-c -g -O3 -mfentry -fomit-frame-pointer -gnatf 
set GNATMAKEARGS=-gnatwu -v -gnato -I%winada% 

cd %INTERFACE_DLL%\%obj%
%gnatbin%\gnatmake %GNATMAKEARGS% ..\hello_dll.adb  -cargs %GCARGS%

Le fichier pour la création de la DLL :

gnatdll -k -d hello_dll.dll obj\hello_dll.ali

Je ne peux pas afficher ici mon fichier pour lequel j'ai produit l'erreur mais j'ai reproduit sur des fichiers plus simples ci-dessous : le fichier adb

with System;
use System;

with Win32;
with Win32.Windef;
with Interfaces.C.Strings;
with Win32.Winuser;
package body HELLO_DLL is
    procedure Report is 
          Result     : Win32.Int         := 0;
          H_Wnd      : Win32.Windef.Hwnd := Null_Address;  
          Lp_Text    : Win32.Lpcstr      := Win32.To_Pcstr (Interfaces.C.Strings.New_String ("Hello World"));  
          Lp_Caption : Win32.Lpcstr      := Win32.To_Pcstr (Interfaces.C.Strings.New_String ("Hello World 2"));  
          U_Type     : Win32.Uint        := 0;  

   begin
      Result := Win32.Winuser.Messagebox (H_Wnd, Lp_Text, Lp_Caption, U_Type);
    end Report;
end HELLO_DLL;

le fichier ads

   with Interfaces.C;
    package HELLO_DLL is

    procedure Report;             
   end HELLO_DLL;

Solution

  • Bonjour :-) It seems that you're missing a reference to the win32ada library in your gnatdll arguments. You might want to try this (note the last three additional arguments):

    gnatdll -k -d hello_dll.dll obj\hello_dll.ali -I"C:\GNAT\2017\lib\win32ada.relocatable" -largs -lwin32ada
    

    However, that being said, I actually think it's easier to create a DLL using a GNAT project file instead of using gnatdll. Based on your example (which I modified a little bit), I created a DLL from the files below and from the command-line in one go. The lib directory will contain a DLL if the build succeeds:

    > gprbuild -p -XWIN32ADA_BUILD=relocatable -P .\hello.gpr
    Setup
       [mkdir]        object directory for project Hello
       [mkdir]        library directory for project Hello
    Compile
       [Ada]          hello.adb
    Build Libraries
       [gprlib]       hello.lexch
       [bind SAL]     hello
       [Ada]          b__hello.adb
       [link library] libhello.dll
    

    with

    src/hello.ads

    package Hello is
    
       procedure Initialize
         with Export, Convention => C;
    
       procedure Finalize
         with Export, Convention => C;
    
       procedure Say_Hello
         with Export, Convention => C;
    
    end Hello;
    

    src/hello.adb

    with System; use System;
    with Interfaces.C.Strings;
    
    with Win32;
    with Win32.Windef;
    with Win32.Winuser;
    
    package body Hello is
    
       ----------------
       -- Initialize --
       ----------------
    
       procedure Initialize is
          procedure helloinit with Import;       --  Generated by binder.
       begin
          helloinit;
       end Initialize;
    
       --------------
       -- Finalize --
       --------------
    
       procedure Finalize is
          procedure hellofinal with Import;      --  Generated by binder.
       begin
          hellofinal;
       end Finalize;
    
       ---------------
       -- Say_Hello --
       ---------------
    
       procedure Say_Hello is
    
          package C_Str renames Interfaces.C.Strings;
    
          C_Text    : C_Str.chars_ptr := C_Str.New_String ("Hello World!");
          C_Caption : C_Str.chars_ptr := C_Str.New_String ("A Hello World Dialog.");
    
          Result : Win32.Int := 0;
    
       begin      
          Result := Win32.Winuser.Messagebox 
            (hWnd      => Null_Address,
             lpText    => Win32.To_Pcstr (C_Text),
             lpCaption => Win32.To_Pcstr (C_Caption),
             uType     => 0);
    
          --  Don't forget to free the allocated strings.
          C_Str.Free (C_Text);
          C_Str.Free (C_Caption);      
    
       end Say_Hello;
    
    end Hello;
    

    hello.gpr

    with "win32ada";
    
    library project Hello is
    
       for Library_Kind use "dynamic";   
       for Library_Name use "hello";
       for Library_Interface use ("hello");
    
       --  The "Library_Auto_Init" option is set to False. This will make the binder
       --  generate initialization and finalization functions (in this case
       --  "helloinit" and "hellofinal"). It's a good habit to wrap these
       --  and call these wrappers from the client application.   
    
       for Library_Auto_Init use "False";
    
       for Library_Dir use "lib";
       for Object_Dir use "obj";
       for Source_Dirs use ("src");
    
    end Hello;
    

    lib/libhello.def (exported symbols, case-sensitive, must be lower case here)

    LIBRARY   LIBHELLO
    EXPORTS
        initialize
        finalize
        say_hello
    

    Extra: Test the DLL with Visual Studio 2019

    To test the DLL, I decided to create a small application using Visual Studio CE 2019. I first created an import library using the Library Manager (lib tool). From the "x64 Native Tools Command Prompt for VS 2019" I invoked:

    > lib /machine:X64 /def:./lib/libhello.def /out:./lib/libhello.lib
    Microsoft (R) Library Manager Version 14.26.28806.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
       Creating library libhello.lib and object libhello.exp
    

    I then the created a new folder and populated it with the source files below and the previously created files libhello.dll, libhello.a and libhello.exp. I finally complied it (again, from the "x64 Native Tools Command Prompt for VS 2019") using

    cl HelloApp.cpp libhello.lib
    Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    HelloApp.cpp
    Microsoft (R) Incremental Linker Version 14.26.28806.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /out:HelloApp.exe
    HelloApp.obj
    libhello.lib
    

    This new HelloApp.exe shows (as expected) a dialog box. Note that the libhello.dll depends on the GNAT runtime library (check with the dependency walker), so make sure that (in your case) C:\GNAT\2017\bin is on the search path when running the application (or copy the required DLLs to the same folder as HelloApp.exe).

    hello.h

    #pragma once
    
    extern "C"
    {
        extern void  say_hello();
        extern void  initialize();
        extern void  finalize();
    }
    

    HelloApp.cpp

    #include <windows.h>
    #include "hello.h"
    
    int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
    {
        UNREFERENCED_PARAMETER(hInstance);
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(pCmdLine);
        UNREFERENCED_PARAMETER(nCmdShow);
    
        initialize();
        say_hello();
        finalize();
    
        return 0;
    }