未定义引用 'do_varargs' with gnat

undefined reference to 'do_varargs' with gnat

编译后,当我尝试使用 win32ada 2017 和 GNAT 2017 构建我的 DLL 时,出现错误:

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:\GNAT17\bin\gcc.exe

你知道为什么 gnatlink 会出现这个错误吗?

编辑:

用于编译的文件位于文件夹中:

@echo on

set GNAT_PATH=C:\GNAT17
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%

创建DLL的文件:

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

我无法查看我的 ci 我的文件,但我在下面复制了更简单的文件 ci: 亚行文件

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;

广告文件

   with Interfaces.C;
    package HELLO_DLL is

    procedure Report;             
   end HELLO_DLL;

Bonjour :-)您似乎在 gnatdll 参数中缺少对 win32ada 库的引用。您可能想试试这个(注意最后三个附加参数):

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

然而,话虽如此,我实际上认为使用 GNAT 项目文件创建 DLL 比使用 gnatdll 更容易。根据您的示例(我稍作修改),我从下面的文件和命令行中一次性创建了一个 DLL。如果构建成功,lib 目录将包含一个 DLL:

> 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

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(导出的符号,区分大小写,这里必须小写)

LIBRARY   LIBHELLO
EXPORTS
    initialize
    finalize
    say_hello

额外:使用 Visual Studio 2019

测试 DLL

为了测试 DLL,我决定使用 Visual Studio CE 2019 创建一个小应用程序。我首先使用库管理器(lib 工具)创建了一个导入库。从 "x64 Native Tools Command Prompt for VS 2019" 我调用了:

> 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

然后我创建了一个新文件夹,并用下面的源文件和之前创建的文件 libhello.dlllibhello.alibhello.exp 填充了它。我最终使用

完成了它(再次来自 "x64 Native Tools Command Prompt for VS 2019")
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

这个新的 HelloApp.exe 显示(如预期的那样)一个对话框。请注意,libhello.dll 取决于 GNAT 运行时库(检查 dependency walker),因此请确保(在您的情况下)C:\GNAT17\bin 在 运行 时在搜索路径上应用程序(或将所需的 DLL 复制到与 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;
}