跳转到内容

Ada 编程/平台/Windows/Visual C++ - GNAT 接口

来自维基教科书,自由的教科书

Ada. Time-tested, safe and secure.
Ada. 经久考验,安全可靠。


本指南介绍了在 Windows 中使用 GNAT 和 MS Visual C++ 从 Ada 连接到 C++ 的方法。

在开始之前,您应该检查您的环境。以下是编写本指南时所使用的环境。

  1. Ada GPL 2006 和 GPS。
  2. Microsoft Visual Studio 2005

我们将遵循以下步骤

  1. 编写您的 Ada 代码并构建动态库
  2. 创建 .lib 文件(用于静态链接)
  3. 协同工作
  4. 运行您的代码

步骤 1. 编写 Ada 源代码

[编辑 | 编辑源代码]
----------------------------- t.ads
 with interfaces.c;
 package t is
 
    package C renames interfaces.c;
 
    procedure test(a,b,z,d,e:c.int) ;
    pragma export (stdcall, test, "test");
 
 end t;
--------------------------------t.adb

 with ada.text_io;
 with t.th;
 package body t is
    procedure test(a,b,z,d,e:c.int) is
       myd : integer := 0;
    begin
       t.th.t.getToken (myd);
       ada.text_io.put_line(myd'img & " and e value is" & c.int'image(e));
    end;
 
 end t;
------------------------------------th.ads
 package t.th is
 
    task T is
       entry getToken (t : out integer);
    end;
 private
 d : integer := 0;
 
 end t.th;
-------------------------------------th.adb

 with ada.text_io;
 package body t.th is
    task body T is
       use ada.text_io;
 
    begin
 
       loop
          select
             accept getToken (t : out integer) do
                t := d;
             end getToken;
          or
             terminate;
          end select;
          d := d + 1;
       end loop;
 
    end ;
 end t.th;

最重要的是您的项目文件。它让您更容易。

project Testdll is
   for Library_Name use "Te";
   for Library_Dir use "dll";
   for Library_Ali_Dir use "ali";
   for Library_Kind use "dynamic";
   for Languages use ("Ada");
   for Object_Dir use "obj";
   for Library_Interface use ("t");

   for Library_Auto_Init use "False";
   for Library_Src_Dir use "dll";
end Testdll;

您可以在 GPS IDE 中配置几乎所有设置。但请注意,GPS 无法正确进行 Library_Interface 设置。配置完成后,您应该检查项目文件并相应地修改它。Library_Interface 指的是 DLL 中包含导出函数的包。

Library_Auto_Init 很有趣,您必须在项目中选择一个正确的设置。

如果选择 True,则库加载时将调用 adaInit(这意味着细化会在加载时间自动出现);如果选择 False,则会在 DLL 中导出 init 和 finalize 函数,您必须自己调用它们。

如果您导出像 C/C++ "普通" 函数一样的函数,没有任何细化部分,则可以将 library_auto_init 设置为 True。

如果您的 Ada 代码不仅仅像 C/C++ 一样工作,而且还需要 Ada 细化函数,那么您应该自己进行初始化/结束处理。

"危险" 危险" 危险" 危险" 危险"

例如,如果您有一个库级任务需要在加载时间进行细化,并且使用隐式链接并加载它,那么当 DllMain 调用 init 代码时,它将 "死锁等待"。这是一种您不希望出现的意外行为。

危险" 危险" 危险" 危险" 危险"

在某些情况下,您可以使用 LoadLibrary / GetProcAddress 来工作(显式加载)。但这并不容易管理您的代码,尤其是在导出许多函数的情况下。

步骤 2. 创建 .lib 文件(用于静态链接)

[编辑 | 编辑源代码]

您可以使用实用程序 dumpbin 和 lib 来生成 .lib 文件(2.A)

    dumpbin/exports Te.dll > te.def,

文件内容是

Microsoft (R) COFF/PE Dumper Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

文件 te.dll 的转储

File Type: DLL
 Section contains the following exports for Te.dll
   00000000 characteristics
   44E2ABD2 time date stamp Wed Aug 16 13:23:30 2006
       0.00 version
          1 ordinal base
         19 number of functions
         19 number of names

   ordinal hint RVA      name

         1    0 00001461 Tefinal
         2    1 000011A0 Teinit
         3    2 00005130 _CRT_MT
         4    3 000050E0 t_E
         5    4 000050D0 t__th_E
         6    5 0000155F t__th__P2sIP
         7    6 00007040 t__th___chain
         8    7 00001745 t__th___elabb
         9    8 0000156E t__th___elabs
        10    9 00007044 t__th___master
        11    A 000050D8 t__th__d
        12    B 00007048 t__th__t
        13    C 00006010 t__th__tT1
        14    D 000016B9 t__th__tTKB
        15    E 000050D1 t__th__tTKE
        16    F 00001490 t__th__tTKVIP
        17   10 000050D4 t__th__tTKZ
        18   11 00005000 temain_E
        19   12 0000178F test@20

 Summary

       1000 .bss
       1000 .data
       1000 .edata
       2000 .idata
       1000 .rdata
       1000 .reloc
      2E000 .stab
      E3000 .stabstr
       4000 .text

(2.b) 删除 Te.def 中的所有内容,但保留...

EXPORTS
         Tefinal
         Teinit
         _CRT_MT
         t_E
         t___elabb
         t__th_E
         t__th__P2sIP
         t__th___elabb
         t__th__d
         t__th__tB
         t__th__tE
         t__th__tVIP
         t__th__tZ
         temain_E
         test@20

Teinit 和 Tefinal 用于在 Te.dll 加载后细化和终止 Ada 细化部分。(名称不叫 adainit/adafinalize,但仍然是 adainit/adafinalize 的相同函数)

步骤 3. 在 MS VC++ 中协同工作

[编辑 | 编辑源代码]

启动 Visual Studio C++ 项目,并将 Te.lib 添加到链接器设置中。

编写一个 Te.h 头文件用于 Ada DLL(GPS 应该为您生成 .lib 和 .h)。

extern "C" extern void _stdcall test(int a,int b,int c,int d,int e);
extern "C" extern void  Teinit();
extern "C" extern void  Tefinal();

并编写一个 C/C++ 测试代码来生成一个 .exe 文件。

#include "stdafx.h" //visual c++ default header
#include "Te.h" //your ada library header
 
int _tmain(int argc, _TCHAR* argv[])
{
 
  Teinit();  //start init
  for (int i = 0 ; i< 300 ;i++)
     test(0,0,0,0,i);
 
  Tefinal(); //end  init
  return 0;
 
}

步骤 4. 运行您的代码

[编辑 | 编辑源代码]

将 .exe 和 .dll 放置在同一个目录中并运行测试。

加载程序将按照以下顺序查找 dll:

  1. 当前目录
  2. path 变量
  3. Windows 目录

将 dll 和 exe 放置在同一个目录中,这是最好的选择。

华夏公益教科书