如何使用 JNA 传递字节
来源:stackoverflow
时间:2024-03-14 18:33:27 264浏览 收藏
今日不肯埋头,明日何以抬头!每日一句努力自己的话哈哈~哈喽,今天我将给大家带来一篇《如何使用 JNA 传递字节》,主要内容是讲解等等,感兴趣的朋友可以收藏或者有更好的建议在评论提出,我都会认真看的!大家一起进步,一起学习!
这是go代码
import ( "c" "fmt" ) //export print func print(keys, values [][]byte) { for len(keys) > 0 { err := txn.set(keys[0], values[0]) errmustbenil(err) fmt.printf("%s %s", string(keys[0]), string(values[0])) keys = keys[1:] values = values[1:] } }
这是libprint.h
/* static assertion to make sure the file is being used on architecture at least with matching size of goint. */ typedef char _check_for_64_bit_pointer_matching_goint[sizeof(void*)==64/8 ? 1:-1]; #ifndef go_cgo_gostring_typedef typedef _gostring_ gostring; #endif typedef void *gomap; typedef void *gochan; typedef struct { void *t; void *v; } gointerface; typedef struct { void *data; goint len; goint cap; } goslice; #endif /* end of boilerplate cgo prologue. */ #ifdef __cplusplus extern "c" { #endif extern void print(goslice keys, goslice values); #ifdef __cplusplus } #endif
这是我的java代码,我想将byte[]一一放入指针中,goslice
代表go
中的array[],我不知道这是否正确 p>
public interface test extends library { test test = (test) native.load("print", test.class); void print(goslice key, goslice val); class goslice extends structure { public pointer[] data; public long len; public long cap; } static void main(string[] args) { byte[] byte1 = "key1".getbytes(standardcharsets.utf_8); byte[] byte2 = "value1new".getbytes(standardcharsets.utf_8); goslice keys = new goslice(); keys.data = new pointer[1]; keys.data[0] = new pointer(byte1.length + 1); keys.len = 1; keys.cap = 1; goslice values = new goslice(); values.data = new pointer[1]; keys.data[0] = new pointer(byte2.length + 1); values.len = 1; values.cap = 1; keys.data[0].write(0, byte1, 0, byte1.length); values.data[0].write(0, byte2, 0, byte2.length); test.test.print(keys, values); } }
但是运行不正常,感觉byte[][]没有正确转换为go中的类型。
这是运行java程序后的控制台日志
# # a fatal error has been detected by the java runtime environment: # # sigsegv (0xb) at pc=0x00000001a2775a34, pid=64329, tid=0x0000000000002903 # # jre version: openjdk runtime environment (zulu 8.62.0.19-ca-macos-aarch64) (8.0_332-b09) (build 1.8.0_332-b09) # java vm: openjdk 64-bit server vm (25.332-b09 mixed mode bsd-aarch64 compressed oops) # problematic frame: # c [libsystem_platform.dylib+0x3a34] _platform_memmove+0xf4 # # failed to write core dump. core dumps have been disabled. to enable core dumping, try "ulimit -c unlimited" before starting java again # # an error report file with more information is saved as: # /users/user/project/hs_err_pid64329.log # # if you would like to submit a bug report, please visit: # http://www.azul.com/support/ #
这是我的第一个改变
public interface txnclient extends library { txnclient tnx_client = (txnclient) native.load("tikv", txnclient.class); int txnsave(goslice[] key, goslice[] val); class goslice extends structure { public long cap; public pointer data; public long len; @override protected listgetfieldorder() { return arrays.aslist("cap", "data", "len"); } } static void main(string[] args) { byte[] key1 = "key1".getbytes(standardcharsets.utf_8); byte[] value1 = "value1new".getbytes(standardcharsets.utf_8); byte[] key2 = "key2".getbytes(standardcharsets.utf_8); byte[] value2 = "value2new".getbytes(standardcharsets.utf_8); goslice tmp = new goslice(); goslice[] keys = (goslice[]) tmp.toarray(2); keys[0].data = new memory(key1.length + 1); keys[0].len = keys[0].cap = key1.length; keys[0].data.write(0, key1, 0, key1.length); keys[1].data = new memory(key2.length + 1); keys[1].len = keys[1].cap = key2.length; keys[1].data.write(0, key2, 0, key2.length); goslice[] values = (goslice[]) tmp.toarray(2); values[0].data = new memory(value1.length + 1); values[0].len = values[0].cap = value1.length; values[0].data.write(0, value1, 0, value1.length); values[1].data = new memory(value2.length + 1); values[1].len = values[1].cap = value2.length; values[1].data.write(0, value2, 0, value2.length); int i = txnclient.tnx_client.txnsave(keys, values); system.out.println(i); } }
5431788016 5431788016panic: runtime error: invalid memory address or nil pointer dereference [signal sigsegv: segmentation violation code=0x2 addr=0x9 pc=0x1225b2b80] goroutine 17 [running, locked to thread]: main.txnsave({0x9, 0x143c281f0, 0x14000182000?}, {0x9, 0x143c281f0, 0x121daf2c8?}) /users/user/project/print.go:52 +0x180
第二次更改
//export txnsave func txnsave(keys, values [][]byte) (res int) { // ignore }
public interface txnclient extends library { txnclient tnx_client = (txnclient) native.load("tikv", txnclient.class); int txnsave(goslice key, goslice val); class goslice extends structure { public long cap; public pointer data; public long len; @override protected listgetfieldorder() { return arrays.aslist("cap", "data", "len"); } } static void main(string[] args) { byte[] key1 = "key1".getbytes(standardcharsets.utf_8); byte[] value1 = "value1new".getbytes(standardcharsets.utf_8); byte[] key2 = "key2".getbytes(standardcharsets.utf_8); byte[] value2 = "value2new".getbytes(standardcharsets.utf_8); goslice keys = new goslice(); keys.data = new memory(key1.length + key2.length + 1); keys.data.write(0, key1, 0, key1.length); keys.len = keys.cap = key1.length + key2.length; keys.data.write(key1.length, key2, 0, key2.length); goslice values = new goslice(); values.data = new memory(value1.length + value2.length + 1); values.len = values.cap = value1.length + value2.length; values.data.write(0, value1, 0, value1.length); values.data.write(value1.length, value2, 0, value2.length); int i = txnclient.tnx_client.txnsave(keys, values); system.out.println(i); } }
[2022/07/31 22:36:57.225 +08:00] [INFO] [client.go:378] ["[pd] create pd client with endpoints"] [pd-address="[127.0.0.1:2379]"] [2022/07/31 22:36:57.228 +08:00] [INFO] [base_client.go:350] ["[pd] switch leader"] [new-leader=http://127.0.0.1:2379] [old-leader=] [2022/07/31 22:36:57.228 +08:00] [INFO] [base_client.go:105] ["[pd] init cluster id"] [cluster-id=7126545341327379321] [2022/07/31 22:36:57.228 +08:00] [INFO] [client.go:673] ["[pd] tso dispatcher created"] [dc-location=global] 4981923696 4981923392panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x8 pc=0x12b00a6e0] // this is error goroutine 17 [running, locked to thread]: main.TxnSave({0x8, 0x128f21f70, 0x14000190000?}, {0x12, 0x128f21e40, 0x12a806d38?}) /Users/user/go-tikv/tikv.go:53 +0x180
正确答案
您误解了 pointer
构造函数的参数。这是本机对等值,而不是分配大小。
你拥有什么:
keys.data[0] = new pointer(byte1.length + 1);
来自 pointer
Javadoc:
分配新内存(内部调用 malloc()
)的正确方法是扩展 pointer
的 memory
类。 memory
构造函数 is indeed the size 的参数:
所以你想要:
keys.data[0] = new Memory(byte1.length + 1);
另外一点:
memory
在分配时不会被清除,因此如果您想要“+1”空终止符,您需要 clear()
内存或在向其写入字符串时显式设置该空字节(或者可能附加一个空字节)在转换为字节之前先将字节转换为 java 中的字符串)。
更新您的后续问题:
c 标头(首先是 data
,后跟 len
和 cap
)与你自己的 goslice
结构定义(将 data
放在中间)之间不匹配。当你将其传递给本机时,你只是发送该初始值long
可能为零,并出现 nil
指针错误。
此外,您没有为您正在执行的操作分配足够的内存。当您在 jna 中声明 structure
时,它会分配所需的内存。在早期版本的代码中,您使用 structure.toarray()
为更多结构分配更多内存——这是正确的(但您做了两次!)。您应该这样做一次。
在最新的代码中,您将 value
设置为一个 goslice
结构。对于两个 long
和 pointer
来说,该内存只有 24 个字节。但是对于第二个数组值,您使用原始的 data
(顺序错误)并尝试写入甚至未分配的内存位置。
总结:
- 在 java
goslice
中声明字段顺序以匹配本机标头 - 在初始 goslice 结构上使用结构的
toarray()
为它们的数组分配空间。 - 使用 goslice[n] 结构的
data
字段写入字符串值。
以上就是《如何使用 JNA 传递字节》的详细内容,更多关于的资料请关注golang学习网公众号!
-
502 收藏
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
139 收藏
-
204 收藏
-
325 收藏
-
477 收藏
-
486 收藏
-
439 收藏
-
357 收藏
-
352 收藏
-
101 收藏
-
440 收藏
-
212 收藏
-
143 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习