Я использую бета-версию Rust 1.0 и смог создать небольшой пример для вызова функций, написанных на Rust с Java. Я просто составил следующий код Rust в mylib.rs с помощью rustc, который производит MyLib.dll на Windows:Вызов ржавчины из Java
#![crate_type = "dylib"]
use std::any::Any;
#[no_mangle]
pub extern fn Java_tests_Test_hello(env: *const Any, jclass: *const Any) {
println!("hello from rust");
}
#[no_mangle]
pub extern fn Java_tests_Test_sum(env: *const Any, jclass: *const Any, a: i32, b: i32) -> i32 {
return a + b;
}
Тогда я могу назвать эти функции из класса Java tests.Test:
package tests;
import java.io.File;
public class Test {
public static native void hello();
public static native int sum(int a, int b);
public static void main(String[] args) {
File f = new File("mylib.dll");
System.load(f.getAbsolutePath());
Test.hello();
System.out.println(Test.sum(20, 22));
}
}
Запуск главного печатает Java ожидаемый результат:
hello from rust
42
в методах Rust я объявил env
как указатель на Any
типа, но в действительности это C s truct с указателями на функции, как описано в documentation (Code example 4-1), которые необходимы для обмена данными со средой выполнения Java.
От этого answer Я понял, что такие структуры с указателями функций должны иметь аналог кода Rust для вызова этих функций. Так что я попытался реализовать такую-структуру установки всех значений полой *mut Any
для GetVersion
поля, за исключением:
#[repr(C)]
pub struct JavaEnv {
reserved0: *mut Any,
reserved1: *mut Any,
reserved2: *mut Any,
reserved3: *mut Any,
GetVersion: extern "C" fn(env: *mut JavaEnv) -> i32,
DefineClass: *mut Any,
FindClass: *mut Any,
…
Когда я вызвать следующую функцию от Java, которая должна вызвать функцию GetVersion, виртуальная машину Аварию:
#[no_mangle]
pub extern fn Java_tests_Test_helloJre(jre: *mut JavaEnv, class: *const Any) {
unsafe {
let v = ((*jre).GetVersion)(jre);
println!("version: {:?}", v);
}
}
Как я могу правильно вызвать функцию GetVersion? Обратите внимание, что я действительно новичок в подобных материалах, поэтому, пожалуйста, не стесняйтесь редактировать этот вопрос, если это необходимо.
Я могу» t дать полный ответ, но вы, кажется, предполагаете, что '* const Any' i s обычный указатель: ** это не **. Это указатель на объект-признак, что означает, что он * в два раза больше обычного указателя *. Вы не должны * использовать '* const Any' для представления« произвольного указателя »; для этого вы должны либо использовать '* const()', либо '* const c_void' (из пакета' libc'). В стороне: вы можете использовать ':: std :: mem :: size_of()', чтобы получить размер данного типа. –
Обратите внимание, что символ «Любой» является признаком, и любой указатель на голый признак является объектом признаков, то есть он на самом деле является «толстым» указателем. Например, программа [this] (http://is.gd/tjze8D) печатает 16 вместо 8. Следовательно, она не подходит для использования в качестве указателя 'void *'. Вам нужно, например, '* mut()' для этого. –