这是我使用JNA和Ada的
Interface.C软件包设法将Java与Ada库接口的方法。
dll非常简单,此处提供的Ada和Java代码至少显示了
char*as in或out参数的2种用法。
可以阅读以下文档:JNA文档,此Ada
Wiki,Ada标准文档和其他一些Ada标准文档。
注意:请注意,以下Java代码可与任何匹配的C接口声明一起使用。请参阅
.h发布后的建议 文件。当然,Java控制台的结果取决于DLL的实现。
初步检查
您需要在Java项目中包含
JNA.jarjar和
JNA-Platform.jar。参见JNA
GitHub进行下载。
确保使用一致的Java和Ada lib体系结构:即32位或64位。否则,JNA / Java将无法加载该库。
也不要忘记使用以下VM选项
-Djna.debug_load=true来查看JNA的登录控制台!
您的Java项目/ bin文件夹应包含以下内容:
- 产生的Ada DLL(使用给定的代码,它将是
libadalib.dll
) - 你的
libgnat-version.dll
- 你的
libgcc_s_seh-1.dll
首先,Ada部分:
请注意,您可能需要在自己的DLL DLL附近放置一些gnat DLL。我目前尚未将所有内容打包到自己的DLL中。
因此,您 可能 需要在产生的dll的同一文件夹(即Java项目的
/bin目录)中包含以下文件:
- 您的libgnat-version.dll
- 您的libgcc_s_seh-1.dll
如果需要解决此问题,请使用DependancyWalker。(请参阅http://www.dependencywalker.com/)
有一个GPR选项可以激活/停用自动DLL详细说明,但我尚未对其进行测试。
Ada码
Ada库项目:
project adalib is for Languages use ("Ada"); for Source_Dirs use (project'Project_Dir & "./src"); for Library_Kind use "dynamic"; -- for DLL for Library_Name use project'Name; -- will produce "libadalib.dll" for Library_Interface use ("ada_interface"); for Library_Dir use project'Project_Dir & "./dll"; for Library_Src_Dir use project'Project_Dir & "./dll"; -- include other DLL / .a here if needed -- for Library_Options use ("-L" & path_to_lib, -- "-l" & path_to_lib -- ); -- define your favorite compiler, builder, binder, linker optionsend adalib;./src ada文件
ada_interface.ads
pragma Ada_2012;with Interfaces.C;with Interfaces.C.Strings;package ada_interface is procedure myService ( inBuffer : in Interfaces.C.Strings.chars_ptr; -- as in anInteger : in Interfaces.C.int; outBuffer : in Interfaces.C.Strings.chars_ptr; -- as out buffer outBufferSize : in Interfaces.C.int; -- max out buffer size usedBufferSize : out Interfaces.C.int ); pragma Export (Convention => C, Entity => myService, External_Name => "Renamed_myService");end ada_interface;
ada_interface.adb
pragma Ada_2012;with Ada.Text_IO;with Interfaces.C.Strings;package body ada_interface is procedure myService ( inBuffer : in Interfaces.C.Strings.chars_ptr; -- as in anInteger : in Interfaces.C.int; outBuffer : in Interfaces.C.Strings.chars_ptr; -- as out buffer outBufferSize : in Interfaces.C.int; -- max out buffer size usedBufferSize : out Interfaces.C.int ) is -- if elaboration needs to be explicitly called procedure ada_elaboration; pragma import (C, ada_elaboration, "adalibinit"); -- "<name of lib>init". May not be needed with proper options in GPR Required_Length : Natural := Natural (outBufferSize); myString : String := "This is a sample string"; use type Interfaces.C.size_t; begin ada_elaboration; -- Ada.Text_IO.Put_Line ("======= inside myService"); -- print the string given by char* Ada.Text_IO.Put_Line (Interfaces.C.Strings.Value (inBuffer)); -- the int Ada.Text_IO.Put_Line (Natural'Image (Natural (anInteger))); -- current value of the char* to be used as OUT buffer Ada.Text_IO.Put_Line (Interfaces.C.Strings.Value (outBuffer)); -- use the char* to be used as out Interfaces.C.Strings.Update (Item => outBuffer, Offset => 0, Str => myString & Interfaces.C.To_Ada (Interfaces.C.nul), -- "& Interfaces.C.To_Ada(Interfaces.C.nul)" is equivalent to "& Character'Val(0)" Check => false); usedBufferSize := Interfaces.C.int (Interfaces.C.Strings.Strlen (outBuffer) - 1); -- see later java pre and traces end myService;end ada_interface;现在的Java代码:
用于将服务加载和映射到库的类:
package tst;import com.sun.jna.Library;import com.sun.jna.Native;import com.sun.jna.Pointer;import com.sun.jna.ptr.IntByReference;public class Ada_Lib { public interface My_Ada_Lib extends Library { My_Ada_Lib instance = (My_Ada_Lib) Native.loadLibrary("libadalib", My_Ada_Lib.class); My_Ada_Lib synchronizedInstance = (My_Ada_Lib) Native.synchronizedLibrary(instance); void Renamed_myService ( Pointer inBuffer, int anInteger, byte[] outBuffer, int outBufferSize, IntByReference usedBufferSize ); }}类调用库
package tst;import com.sun.jna.Memory;import com.sun.jna.Native;import com.sun.jna.Pointer;import com.sun.jna.ptr.IntByReference;import tst.Ada_Lib.My_Ada_Lib;public class TestMyLib { private static My_Ada_Lib theLib = Ada_Lib.My_Ada_Lib.synchronizedInstance; public static void main(String[] args) { String lorem = "Sin autem ad adulescentiam perduxissent, dirimi tamen interdum contentione vel uxoriae condicionis vel commodi alicuius, quod idem adipisci uterque non posset. Quod si qui longius in amicitia provecti essent, tamen saepe labefactari, si in honoris contentionem incidissent; pestem enim nullam maiorem esse amicitiis quam in plerisque pecuniae cupiditatem, in optimis quibusque honoris certamen et gloriae; ex quo inimicitias maximas saepe inter amicissimos exstitisse." + "n" + "Quanta autem vis amicitiae sit, ex hoc intellegi maxime potest, quod ex infinita societate generis humani, quam conciliavit ipsa natura, ita contracta res est et adducta in angustum ut omnis caritas aut inter duos aut inter paucos iungeretur." + "n" + "Haec subinde Constantius audiens et quaedam referente Thalassio doctus, quem eum odisse iam conpererat lege communi, scribens ad Caesarem blandius adiumenta paulatim illi subtraxit, sollicitari se simulans ne, uti est militare otium fere tumultuosum, in eius perniciem conspiraret, solisque scholis iussit esse contentum palatinis et protectorum cum Scutariis et Gentilibus, et mandabat Domitiano, ex comite largitionum, praefecto ut cum in Syriam venerit, Gallum, quem crebro acciverat, ad Italiam properare blande hortaretur et verecunde.n"; // in params int inputInt = 25; Pointer p_Lorem = new Memory(lorem.length()+1); // +1 for C's p_Lorem.setString(0, lorem); // offset 0, no need to start at another offset // in param but to used for out buffer String stubOut = "Hello World ! 0123456789 "; int maxBufferSize = (stubOut.length()); byte[] buffer = new byte[maxBufferSize]; buffer = stubOut.getBytes(); IntByReference usedBufferSize = new IntByReference(0); // any value works, since it is used as out param System.out.println("-------------------- Call to Lib ----------------------------"); // call the lib ! theLib.Renamed_myService(p_Lorem, inputInt, buffer, maxBufferSize, usedBufferSize); System.out.println("--------------------- Back to java --------------------------"); System.out.println("In Java: used buffer size = " + usedBufferSize.getValue()); System.out.println("In Java: read outBuffer as String = " + Native.toString(buffer)); System.out.println("In Java: read outBuffer as String with returned used buffer size = " + new String(buffer,0,usedBufferSize.getValue())); }}来自Java控制台的输出(JNA debug为true)
Looking in classpath from sun.misc.Launcher$AppClassLoader@4e0e2f2a for /com/sun/jna/win32-x86-64/jnidispatch.dllFound library resource at jar:file:/ [...]Looking for library 'libadalib'Adding paths from jna.library.path: nullTrying libadalib.dllAdding system paths: []Trying libadalib.dllLooking for lib- prefixTrying liblibadalib.dllLooking in classpath from sun.misc.Launcher$AppClassLoader@4e0e2f2a for libadalibFound library resource at file:/<path>/TestMyLib/bin/libadalib.dllLooking in <path>TestMyLibbinlibadalib.dllFound library 'libadalib' at <path>TestMyLibbinlibadalib.dll-------------------- Call to Lib ----------------------------======= inside myServiceSin autem ad adulescentiam perduxissent, dirimi tamen interdum contentione vel uxoriae condicionis vel commodi alicuius, quod idem adipisci uterque non posset. Quod si qui longius in amicitia provecti essent, tamen saepe labefactari, si in honoris contentionem incidissent; pestem enim nullam maiorem esse amicitiis quam in plerisque pecuniae cupiditatem, in optimis quibusque honoris certamen et gloriae; ex quo inimicitias maximas saepe inter amicissimos exstitisse.Quanta autem vis amicitiae sit, ex hoc intellegi maxime potest, quod ex infinita societate generis humani, quam conciliavit ipsa natura, ita contracta res est et adducta in angustum ut omnis caritas aut inter duos aut inter paucos iungeretur.Haec subinde Constantius audiens et quaedam referente Thalassio doctus, quem eum odisse iam conpererat lege communi, scribens ad Caesarem blandius adiumenta paulatim illi subtraxit, sollicitari se simulans ne, uti est militare otium fere tumultuosum, in eius perniciem conspiraret, solisque scholis iussit esse contentum palatinis et protectorum cum Scutariis et Gentilibus, et mandabat Domitiano, ex comite largitionum, praefecto ut cum in Syriam venerit, Gallum, quem crebro acciverat, ad Italiam properare blande hortaretur et verecunde. 25Hello World ! 0123456789--------------------- Back to java --------------------------In Java: used buffer size = 22In Java: read outBuffer as String = This is a sample string // reads the full bufferIn Java: read outBuffer as String with returned used buffer size = This is a sample strin // reads a length of 22 (so the 'g' is missing)
现在,也可以使用匹配的.h文件轻松将Ada库与C或C ++接口:
void myService (char* inBuffer, // as in string int anInteger, // as in param char* outBuffer, // used as out buffer, but initalized by calling pre int outBufferSize, // the initaliaed size int usedBufferSize // used as out param, the actually used size);
从Eclipse调用时如何调试lib?
使用Gnat Pro
Studio(GPS),您可以进入调试器视图,并将gdb附加到Java应用程序进程的PID(对于Windows)。但是,如果没有以下技巧,您将无法设置断点。
诀窍是在DLL中有一个无限循环(出于开发目的)。
身体:
while flag loop null;end loop;
广告文件:
flag : boolean := true; -- in private part
一旦gdb设法附加到正在运行的DLL代码(无限循环),gdb就会崩溃。
在循环中放置一个断点,然后在gdb中输入类型
c。它将在您的循环中中断。
在代码中的其他地方放置另一个断点,然后键入follwong
set flag := false,然后输入
c。
现在,gdb应该继续到下一个断点。
(或使用“ n”(下一条)gdb指令自行调试。)



