- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我必须编写一个 DLL 来提供一个简单的服务,它需要:
从 C 的角度来看,签名应该是这样的:
void myService (char* inBuffer, // as in string
int anInteger, // as in param
char* outBuffer, // used as out buffer, but initalized by calling code
int outBufferSize, // the initaliaed size
int usedBufferSize // used as out param, the actually used size
);
出于多种原因,选择在 Ada 中对库进行编码(多个 Ada 包重复使用,我们不想再次编码也不想重新设计(遗留))。该库应该在 Java 项目中使用(我们不想从 Java 端重新编码 lib 提供的服务)。(主要原因是该库隐藏了复杂的 Ada 类型转换为 JSON + 协议(protocol)库。)
future 库也将与C或C++接口(interface),所以主要思想是依赖基本类型。
如何同时对接 C 和 Java?
(我找到了一个解决方案,所以我想在下面分享详细信息;查看我自己的答案。由于旧的工作场所网络浏览器非常错误,无法使用复选框来完成...)
最佳答案
下面是我如何使用 JNA 和 Ada 的 Interface.C
包将 Java 与 Ada 库连接起来。
dll 相当简单,此处提供的 Ada 和 Java 代码至少显示了 char*
的两种用法作为输入或输出参数。
可以阅读以下文档:JNA documentation、this Ada wiki、Ada standard doc 和 some other Ada standard doc。
注意:请注意,以下 Java 代码可以与任何匹配的 C 接口(interface)声明一起使用。请参阅帖子末尾建议的 .h
文件。当然,Java 控制台结果将取决于 DLL 实现。
您需要在 java 项目中包含 JNA.jar
jar 和 JNA-Platform.jar
。参见 JNA GitHub 下载。
一定要使用一致的 Java 和 Ada lib 架构:即都是 32 位或都是 64 位。否则,JNA/Java 将无法加载该库。
不要忘记使用以下 VM 选项 -Djna.debug_load=true
来查看 JNA 的登录控制台!
您的 Java 项目/bin 文件夹应包含以下内容:
libadalib.dll
)libgnat-version.dll
libgcc_s_seh-1.dll
请注意,您可能需要将一些 gnat DLL 放在您自己的 DLL 附近。我目前还没有设法将所有内容打包到我自己的 DLL 中。
因此您可能需要在生成的 dll 的同一文件夹中包含以下内容(即您的 Java 项目的 /bin
目录):
如果需要解决这个问题,请使用 DependancyWalker。 (见 http://www.dependencywalker.com/ )
有一个 GPR 选项可以激活/停用自动 DLL 细化,但我还没有测试过它。
阿达代码
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 options
end 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 code and traces
end myService;
end ada_interface;
加载服务并将服务映射到库的类:
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 \0
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\0";
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 调试为真)
Looking in classpath from sun.misc.Launcher$AppClassLoader@4e0e2f2a for /com/sun/jna/win32-x86-64/jnidispatch.dll
Found library resource at jar:file:/ [...]
Looking for library 'libadalib'
Adding paths from jna.library.path: null
Trying libadalib.dll
Adding system paths: []
Trying libadalib.dll
Looking for lib- prefix
Trying liblibadalib.dll
Looking in classpath from sun.misc.Launcher$AppClassLoader@4e0e2f2a for libadalib
Found library resource at file:/<path>/TestMyLib/bin/libadalib.dll
Looking in <path>\TestMyLib\bin\libadalib.dll
Found library 'libadalib' at <path>\TestMyLib\bin\libadalib.dll
-------------------- Call to Lib ----------------------------
======= inside myService
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.
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.
25
Hello World ! 0123456789
--------------------- Back to java --------------------------
In Java: used buffer size = 22
In Java: read outBuffer as String = This is a sample string // reads the full buffer
In 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)
现在 Ada 库也可以使用匹配的 .h 文件轻松地与 C 或 C++ 接口(interface):
void myService (char* inBuffer, // as in string
int anInteger, // as in param
char* outBuffer, // used as out buffer, but initalized by calling code
int outBufferSize, // the initaliaed size
int usedBufferSize // used as out param, the actually used size
);
如何在从 Eclipse 调用时调试库?
使用 Gnat Pro Studio (GPS),您可以进入调试器 View 并将 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”(next)gdb指令自行调试。)
关于java - 使用 JNA 和 Ada 的 Interface.C 包将 Ada 动态库与 Java 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42938883/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!