我使用Visual Studio 2017编译了以下C ++方法:
extern "C" __declspec( dllexport )
Info* __stdcall GetInfo(InfoProvider* infoProvider)
{
static_assert(std::is_pod<Info>::value, "Must be Plain Old Data in order to be safely copied between DLL boundaries");
Info info = new Info();
Info->data1 = infoProvider->data1;
Info->data2 = infoProvider->data2;
return info;
}
Run Code Online (Sandbox Code Playgroud)
在Java代码中,它由Java Native Runtime使用具有以下签名的接口方法进行映射:
Info GetInfo(Pointer infoProvider);
final class Info extends Struct {
public final Signed32 data1;
public final Signed32 data2;
public R2VInfo(final Runtime runtime) {
super(runtime);
data1 = new Signed32();
data2 = new Signed32();
}
}
Run Code Online (Sandbox Code Playgroud)
有用。 …
根据这里的图片

这两个库都按照相同的原理工作。但是我相信它们之间是有区别的。这有什么区别?
使用python的ctypes,可以指定一个采用类型的指针:
class METADATA(Structure):
_fields_ = [("classes", c_int),
("names", POINTER(c_char_p))]
Run Code Online (Sandbox Code Playgroud)
使用JNR,它看起来像这样:
public static class Metadata extends Struct{
public Metadata(jnr.ffi.Runtime rt) {
super(rt);
}
public final Struct.Unsigned32 classes = new Struct.Unsigned32();
public final Struct.Pointer names = new Struct.Pointer();
}
Run Code Online (Sandbox Code Playgroud)
但是,是否可以将names字段键入为字符串的指针?
我正在使用JNR并尝试传递具有以下C等效签名的回调函数:
int fn(void const*, void const**, void**)
Run Code Online (Sandbox Code Playgroud)
进入一些C函数。我已将嵌套在Java方面的JNR库接口中的回调声明为:
public static interface Fn {
@Delegate public int call(Pointer a, Pointer[] b, Pointer[] c);
}
Run Code Online (Sandbox Code Playgroud)
在JNR库界面中具有另一个功能
public int doSomething(Fn fn);
Run Code Online (Sandbox Code Playgroud)
用作doSomethingC代码接受中的包装int(*)(void const*, void const**, void**)。但是每当我创建一个回调时:
new Fn() { int call() { ... } };
Run Code Online (Sandbox Code Playgroud)
并将其传递给doSomething我的JNR库接口的方法,我得到运行时错误:
java.lang.ExceptionInInitializerError
Caused by:
java.lang.IllegalArgumentException: unsupported closure parameter type class [Ljnr.ffi.Pointer;
at jnr.ffi.provider.jffi.NativeClosureProxy.newProxyFactory(NativeClosureProxy.java:109)
at jnr.ffi.provider.jffi.NativeClosureFactory.newClosureFactory(NativeClosureFactory.java:84)
at jnr.ffi.provider.jffi.NativeClosureManager.initClosureFactory(NativeClosureManager.java:71)
at jnr.ffi.provider.jffi.NativeClosureManager.getClosureFactory(NativeClosureManager.java:49)
at jnr.ffi.provider.jffi.NativeClosureManager.newClosureSite(NativeClosureManager.java:81)
at jnr.ffi.provider.jffi.InvokerTypeMapper.getToNativeConverter(InvokerTypeMapper.java:68)
at jnr.ffi.provider.jffi.InvokerTypeMapper.getToNativeType(InvokerTypeMapper.java:143)
at jnr.ffi.mapper.CachingTypeMapper.lookupAndCacheToNativeType(CachingTypeMapper.java:71)
at jnr.ffi.mapper.CachingTypeMapper.getToNativeType(CachingTypeMapper.java:43)
at jnr.ffi.mapper.CompositeTypeMapper.getToNativeType(CompositeTypeMapper.java:34)
at …Run Code Online (Sandbox Code Playgroud) 我知道一种方法- memcpy在C ++端使用:
C ++方法:
void CopyData(void* buffer, int size)
{
memcpy(buffer, source, size);
}
Run Code Online (Sandbox Code Playgroud)
JNR映射:
void CopyData(@Pinned @Out ByteBuffer byteBuffer, @Pinned @In int size);
Run Code Online (Sandbox Code Playgroud)
Java调用:
ByteBuffer buffer = ByteBuffer.allocateDirect(size);
adapter.CopyData(buffer, size);
Run Code Online (Sandbox Code Playgroud)
但是我想处理本机代码不复制数据,而只返回指向要复制的内存的情况:
C ++方法:
void* GetData1()
{
return source;
}
// or
struct Data
{
void* data;
};
void* GetData2(Data* outData)
{
outData->data = source;
}
Run Code Online (Sandbox Code Playgroud)
我知道如何编写JNR映射以将数据复制到HeapByteBuffer:
Pointer GetData1();
// or
void GetData2(@Pinned @Out Data outData);
final class Data extends Struct {
public final Struct.Pointer data; …Run Code Online (Sandbox Code Playgroud) 在 Rust 中,我有一个压缩数组的函数:
fn create_bitvec(data: Box<[u8]>) -> [u8; 49152] {
let mut bit_vector = [0u8; 49152];
for (index, &value) in data.iter().enumerate() {
let byte_index = (index * 4) / 8;
let bit_index = (index * 4) % 8;
let value_mask = 0b00001111 << bit_index;
let shifted_value = (value << bit_index) & value_mask;
bit_vector[byte_index] &= !value_mask;
bit_vector[byte_index] |= shifted_value;
}
debug!("made it here. {:?}", bit_vector);
bit_vector
}
Run Code Online (Sandbox Code Playgroud)
(很抱歉,如果函数的实现不好,但这不是这里的具体问题)。
该函数的使用方式如下:
pub fn create(data: Box<[u8]>) -> Chunk {
assert_eq!(data.len(), FULL, "Data length doesn't …Run Code Online (Sandbox Code Playgroud) 我有以下c代码:
#include <stdio.h>
struct Second {
int a_number;
};
struct Top {
struct Second second;
};
void lets_go(struct Top *top) {
printf("The number is %d\n", top->second.a_number);
}
Run Code Online (Sandbox Code Playgroud)
我想从 Java 中执行此操作:
int main(void) {
struct Top top = {{8}};
lets_go(&top);
}
Run Code Online (Sandbox Code Playgroud)
我也想使用jnr-ffi,所以我查看了测试并最终得到以下结果:
package structs.playing;
import structs.playing.Program.Test.Top;
import structs.playing.Program.Test.Second;
import jnr.ffi.LibraryLoader;
import jnr.ffi.Runtime;
import jnr.ffi.Struct;
public final class Program {
public static interface Test {
void lets_go(Top top);
public static final class Second extends Struct {
public final Signed32 a_number …Run Code Online (Sandbox Code Playgroud)