Ada 编程/平台/Windows/Visual C++ - GNAT 接口
本指南介绍了在 Windows 中使用 GNAT 和 MS Visual C++ 从 Ada 连接到 C++ 的方法。
在开始之前,您应该检查您的环境。以下是编写本指南时所使用的环境。
- Ada GPL 2006 和 GPS。
- Microsoft Visual Studio 2005
我们将遵循以下步骤
- 编写您的 Ada 代码并构建动态库
- 创建 .lib 文件(用于静态链接)
- 协同工作
- 运行您的代码
----------------------------- t.adswithinterfaces.c;packagetispackageCrenamesinterfaces.c;proceduretest(a,b,z,d,e:c.int) ;pragmaexport (stdcall, test, "test");endt;
--------------------------------t.adbwithada.text_io;witht.th;packagebodytisproceduretest(a,b,z,d,e:c.int)ismyd : integer := 0;begint.th.t.getToken (myd); ada.text_io.put_line(myd'img & " and e value is" & c.int'image(e));end;endt;
------------------------------------th.adspackaget.thistaskTisentrygetToken (t :outinteger);end;privated : integer := 0;endt.th;
-------------------------------------th.adbwithada.text_io;packagebodyt.thistaskbodyTisuseada.text_io;beginloopselectacceptgetToken (t :outinteger)dot := d;endgetToken;orterminate;endselect; d := d + 1;endloop;end;endt.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 来工作(显式加载)。但这并不容易管理您的代码,尤其是在导出许多函数的情况下。
您可以使用实用程序 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 的相同函数)
启动 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;
}
将 .exe 和 .dll 放置在同一个目录中并运行测试。
加载程序将按照以下顺序查找 dll:
- 当前目录
- path 变量
- Windows 目录
将 dll 和 exe 放置在同一个目录中,这是最好的选择。
