使用 JNI 将数据从 Java 复制到 C++ 对象数组
Copying Data from Java to C++ Objects Array Using JNI
我有 Java 需要大量计算的代码,我想使用 JNI 将其转发到 C++。
我主要关心的是将所有数据序列化在内存中,然后将计算转发给 GPU。
由于数据是在 Java 中接收的,但主要计算是使用 C++ 完成的,所以我想到将所有数据连续排列在原始数组中(ByteBuffer
或来自 Unsafe
的原始字节),与 C++ 对象的结构相同。
例如,假设我有 x
和 y
的观点。在 C++ 中,对象的大小为 24 字节。 8 个字节用于(我猜)VTable,8 个字节用于 x
和 8 个字节用于 y
。
所以在 Java 中,我会将所有数据安排在相同的结构中,并使用 JNI 将缓冲区传递给 C++,然后在 C++ 中将其转换为点数组。
这很好用,我允许自己假设我将始终使用相同的 C++ 编译器、相同的 JDK、相同的 OS 和相同的硬件(至少用于测试可行性解决方案)。
我的问题是这些假设是否正确,或者有更好的方法在 Java 和 C++ 之间传递序列化数据(我必须使用 JNI 而不是某种 IPC)?
if I can rely on the C++ structure (offset, alignment of the fields, etc.)
不,除非您知道特定平台上的编译器在这种情况下会做什么。它会产生未定义的行为。
使用 Point *
将 ByteBuffer
(又名 char *
)的内容别名化以在以后访问其成员在惯用的 C 中是不可能的。看看 C 标准 N1570 6.5 (p7)
:
An object shall have its stored value accessed only by an
lvalue expression that has one of
the following types:88)
— a type compatible with the effective type of the object,
假设您知道 GetDirectBufferAddress
返回的 void *
本身是通过调用 malloc(size)
或朋友(它实际上使用 malloc
)返回的,其中 size_t size = sizeof(struct Point)
而不是你可以将它转换为 Point *
从 本机代码 初始化它的成员,然后再使用它。那将是一种符合标准的方式(其中之一)。
我有 Java 需要大量计算的代码,我想使用 JNI 将其转发到 C++。
我主要关心的是将所有数据序列化在内存中,然后将计算转发给 GPU。
由于数据是在 Java 中接收的,但主要计算是使用 C++ 完成的,所以我想到将所有数据连续排列在原始数组中(ByteBuffer
或来自 Unsafe
的原始字节),与 C++ 对象的结构相同。
例如,假设我有 x
和 y
的观点。在 C++ 中,对象的大小为 24 字节。 8 个字节用于(我猜)VTable,8 个字节用于 x
和 8 个字节用于 y
。
所以在 Java 中,我会将所有数据安排在相同的结构中,并使用 JNI 将缓冲区传递给 C++,然后在 C++ 中将其转换为点数组。
这很好用,我允许自己假设我将始终使用相同的 C++ 编译器、相同的 JDK、相同的 OS 和相同的硬件(至少用于测试可行性解决方案)。
我的问题是这些假设是否正确,或者有更好的方法在 Java 和 C++ 之间传递序列化数据(我必须使用 JNI 而不是某种 IPC)?
if I can rely on the C++ structure (offset, alignment of the fields, etc.)
不,除非您知道特定平台上的编译器在这种情况下会做什么。它会产生未定义的行为。
使用 Point *
将 ByteBuffer
(又名 char *
)的内容别名化以在以后访问其成员在惯用的 C 中是不可能的。看看 C 标准 N1570 6.5 (p7)
:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)
— a type compatible with the effective type of the object,
假设您知道 GetDirectBufferAddress
返回的 void *
本身是通过调用 malloc(size)
或朋友(它实际上使用 malloc
)返回的,其中 size_t size = sizeof(struct Point)
而不是你可以将它转换为 Point *
从 本机代码 初始化它的成员,然后再使用它。那将是一种符合标准的方式(其中之一)。