如何使用 java.nio.ByteBuffer 从 C++ 返回到 Java

2024-04-15

这几乎是问题的重复如何使 Swig 正确包装在 C 中修改为 Java Something-or-other 的 char* 缓冲区? https://stackoverflow.com/questions/2740068/how-can-i-make-swig-correctly-wrap-a-char-buffer-that-is-modified-in-c-as-a-jav ...
如果我使用字节缓冲区而不是 Stringbuffer,类型映射会发生什么变化?


我整理了一个示例,说明如何使用以下头文件/函数作为测试来执行此操作:

#include <stdio.h>

static void foo(char *buf, int len) {
  while(len--)
    putchar(*buf++);
}

我的解决方案是修改这个答案 https://stackoverflow.com/questions/11584599/pass-an-array-to-a-wrapped-function-as-pointersize-or-range/11584600#11584600这样代理就需要一个ByteBuffer并将其转换为byte[]供我们传递给 JNI 代码,然后 JNI 代码将其转换为指针 + 长度组合。

%module test

%{
#include "test.h"
%}

%typemap(jtype) (char *buf, int len) "byte[]"
%typemap(jstype) (char *buf, int len) "java.nio.ByteBuffer"
%typemap(jni) (char *buf, int len) "jbyteArray"
%typemap(javain,pre="    byte[] temp$javainput = new byte[$javainput.capacity()];"
                    "    $javainput.get(temp$javainput);")
        (char *buf, int len) "temp$javainput"

%typemap(in,numinputs=1) (char *buf, int len) {
  $1 = JCALL2(GetByteArrayElements, jenv, $input, NULL);
  $2 = JCALL1(GetArrayLength, jenv, $input);
}

%typemap(freearg) (const signed char *arr, size_t sz) {
  // Or use  0 instead of ABORT to keep changes if it was a copy
  JCALL3(ReleaseByteArrayElements, jenv, $input, $1, JNI_ABORT); 
}

%include "test.h"

这里的新位位于 javain 类型映射中,分配一个临时的byte[]然后使用get来填充它。实际上有一个array()函数表示如果ByteBuffer您正在使用您应该使用的支持,即类型映射应该只是:

%typemap(javain) (char *buf, int len) "$javainput.array()"

如果您的实现支持它(该方法是可选的并且可能会抛出UnsuportedOperationException).

事实上,这可以通过 SWIG 2.0 进一步简化,从前面引用的问题来看,因为我们期望类型为always be byte我们可以使用 SWIG 2.0 中的内置 int 类型映射来简化我们的界面,现在变成:

%module test

%{
#include "test.h"
%}

%apply (char *STRING, size_t LENGTH) { (char *buf, int len) }
%typemap(javain) (char *buf, int len) "$javainput.array()"
%typemap(jstype) (char *buf, int len) "java.nio.ByteBuffer"

%include "test.h"

我使用以下 Java 测试了所有三个版本:

public class run {
  public static void main(String[] argv) {
    System.loadLibrary("test");
    byte value[] = "hello world\n".getBytes();
    java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(value);
    test.foo(buf);
  }
}

为了安全地应对可能不受支持的情况array()您可能想要做的是在带有编译指示的函数中添加 try/catch:

%pragma(java) modulecode = %{
  private static byte[] buf2bytearr(java.nio.ByteBuffer buf) {
    try {
      return buf.array();
    }
    catch (UnsupportedOperationException e) {
      byte arr[] = new byte[buf.capacity()];
      buf.get(arr);
      return arr;
    }
  }
%}

然后修改类型映射以使用:

%typemap(javain) (char *buf, int len) "buf2bytearr($javainput)"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 java.nio.ByteBuffer 从 C++ 返回到 Java 的相关文章

  • 如何将 currentTimeMillis 转换为可读的日期格式? [复制]

    这个问题在这里已经有答案了 我想用currentTimeMillis两次 这样我就可以计算持续时间 但我也想以用户可读的格式显示时间和日期 我遇到了麻烦currentTimeMillis有利于计算 但我看不到内置函数可以转换为合适的时间或时
  • 单线程公寓问题

    从我的主窗体中 我调用以下命令来打开一个新窗体 MyForm sth new MyForm sth show 一切都很好 但是这个表单有一个组合框 当我将其 AutoCompleteMode 切换为建议和追加时 我在显示表单时遇到了这个异常
  • 如何使用 UUID 生成唯一的正 Long

    我需要为我的数据库主键列生成唯一的长 ID 我以为我可以用UUID randomUUID getMostSignificantBits 但有时它也会产生一些负多头 这对我来说是个问题 是否可以从 UUID 中仅生成正长 将会有数十亿个条目
  • C# datagridview 列转入数组

    我正在用 C 构建一个程序 并在其中包含一个 datagridview 组件 datagridview 有固定数量的列 2 我想将其保存到两个单独的数组中 但行数确实发生了变化 我怎么能这样做呢 假设一个名为 dataGridView1 的
  • 编译器错误“错误:在文件范围内可变地修改了‘字符串’”

    考虑 include
  • 您可以在一个 Windows Azure 实例上部署多个 Web 应用程序吗?

    是否可以在一个 windows azure 小型计算实例中运行一堆 Web 应用程序 我正在考虑使用 Azure 作为放置一堆处于开发和非生产状态的项目 Web 应用程序 的地方 有些实际上已经被封存了 但我想在某个地方有一个活跃的实例 我
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • EclipseLink 2.7.0 和 JPA API 2.2.0 - 签名不匹配

    当运行由maven构建的具有以下依赖项的项目时
  • 系统错误 124 - SHFileOperation 的 ERROR_INVALID_LEVEL

    我在使用时遇到问题SHFileOperation SHFileOperation SHFILEOPSTRUCT https stackoverflow com questions 9191415 shfileoperation shfile
  • 从事务范围调用 WCF 服务方法

    我有这样的代码 using TransactionScope scope TransactionScopeFactory CreateTransactionScope some methodes calls for which scope
  • Android - 保持用户登录状态

    我正在尝试使用 PHP 和 MySQLi for Android 进行登录 我不明白的是如何保持用户登录状态 我看到一个简单的教程 其中有人使用 SQLite 来保护信息 但我不知道这是否真的安全 如何保存用户信息以保持用户登录状态 谢谢
  • HashSet 与 LinkedHashSet

    它们之间有什么区别 我知道 LinkedHashSet 是 HashSet 的有序版本 维护一个跨所有元素的双向链接列表 使用此类代替 HashSet 当您关心迭代顺序时 当你迭代 HashSet 时 顺序是不可预测的 而 LinkedHa
  • 线程睡眠阻止我的 Swing 应用程序执行

    我的应用程序发生的事情是有道理的 但我不知道如何修复它 以下是我的应用程序功能的简要描述 计时器窗口应显示在屏幕右下角并显示实时时间 一小时后 它应该执行一些操作 我还没有决定该操作 我面临的问题是定时器 java当我刷新实时计时器的秒数时
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • 如何将多部分文件从另一个服务发送到一个服务

    我有两个端点 api 它们是 uploadand 重定向 upload是我直接上传文件的地方 重定向是我接收文件并将其传递给上传并获取 JSON 响应的地方 upload 所以下面是我的代码 package com example impo
  • C++ [Windows] 可执行文件所在文件夹的路径[重复]

    这个问题在这里已经有答案了 我需要访问一些文件fstream在我的 Windows 上的 C 应用程序中 这些文件都位于我的exe文件所在文件夹的子文件夹中 获取当前可执行文件的文件夹路径的最简单且更重要的 最安全的方法是什么 Use 获取
  • Android应用程序中的模式输入

    我想知道是否有其他替代方案可以替代 Android 上平庸的 EditText 密码输入 是否有 API 或开源代码可以集成到我的应用程序中 类似于锁屏图案解锁 Intent 可能会返回哈希值 数字 字符串或代表用户输入的模式的任何内容 我
  • javafx中的stackpane和root有什么区别?

    我正在练习javafx做饼图 以下是开发饼图的代码 如果我这样做Group并与StackPane 我发现输出没有区别 我已经评论了组部分 只是徘徊两者之间的区别 import javafx application Application i
  • 按字母顺序对对象的 ArrayList 进行排序

    我必须创建一个方法来排序数组列表根据电子邮件按字母顺序排列对象 然后打印排序后的数组 我在排序时遇到麻烦的部分 我已经研究过并尝试使用Collections sort vehiclearray 但这对我不起作用 我是因为我需要一个叫做比较器

随机推荐