first commit
This commit is contained in:
commit
e2c095af41
34 changed files with 667 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
49
Cargo.lock
generated
Normal file
49
Cargo.lock
generated
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.157"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "374af5f94e54fa97cf75e945cce8a6b201e88a1a07e688b47dfd2a59c66dbd86"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "makepad-android-state"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd004cda8be459fd76954218b76a1249a079fb9360bbca4e724cb7ddb2962857"
|
||||||
|
dependencies = [
|
||||||
|
"makepad-jni-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "makepad-jni-sys"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9775cbec5fa0647500c3e5de7c850280a88335d1d2d770e5aa2332b801ba7064"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-interop"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"makepad-android-state",
|
||||||
|
"makepad-jni-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
30
Cargo.toml
Normal file
30
Cargo.toml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
[package]
|
||||||
|
name = "rust-interop"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "rust_interop"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
# [bin]
|
||||||
|
# name = "_rust_interop"
|
||||||
|
# path = "examples/interop.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
libc = "0.2.157"
|
||||||
|
makepad-jni-sys = "0.4.0"
|
||||||
|
makepad-android-state = "0.1.0"
|
||||||
|
# makepad-android-state = { path = "../makepad/libs/android_state", version = "0.1.0" }
|
||||||
|
# makepad-jni-sys = { path = "../makepad/libs/jni-sys", version = "0.4.0" }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = "1.1.13"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
build = "build.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["android-result"]
|
||||||
|
android-result = []
|
0
README.md
Normal file
0
README.md
Normal file
99
build.rs
Normal file
99
build.rs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
use std::{path::Path, process::Command};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
compile_java();
|
||||||
|
compile_c();
|
||||||
|
compile_objc();
|
||||||
|
compile_swift();
|
||||||
|
link_libraries();
|
||||||
|
|
||||||
|
// Run the Java command after the build
|
||||||
|
if let Err(e) = run_java_command() {
|
||||||
|
panic!("Failed to run Java command: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_java() {
|
||||||
|
// Compile Java code using `javac`
|
||||||
|
println!("cargo:rerun-if-changed=java/HelloWorld.java");
|
||||||
|
let java_compile_status = Command::new("javac")
|
||||||
|
.arg("-d")
|
||||||
|
.arg("java") // Output directory for .class files
|
||||||
|
.arg("java/HelloWorld.java")
|
||||||
|
.status()
|
||||||
|
.expect("Failed to compile Java code");
|
||||||
|
if !java_compile_status.success() {
|
||||||
|
panic!("Java compilation failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn run_java_command() -> std::io::Result<()> {
|
||||||
|
let java_class_path = "./java";
|
||||||
|
let java_library_path = "./target/release";
|
||||||
|
|
||||||
|
Command::new("java")
|
||||||
|
.arg("-cp")
|
||||||
|
.arg(java_class_path)
|
||||||
|
.arg("-Djava.library.path")
|
||||||
|
.arg(java_library_path)
|
||||||
|
.arg("HelloWorld")
|
||||||
|
.status()
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_c() {
|
||||||
|
// Compile C code
|
||||||
|
cc::Build::new()
|
||||||
|
.file("c/example.c")
|
||||||
|
.include("c") // Include directory for header files
|
||||||
|
.compile("example");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_objc() {
|
||||||
|
// Compile Objective-C code
|
||||||
|
cc::Build::new()
|
||||||
|
.file("objc/MyClass.m") // Path to your Objective-C source file
|
||||||
|
.includes(&["objc"]) // Include necessary directories
|
||||||
|
.flag("-ObjC") // Objective-C flag for linking all categories and classes
|
||||||
|
.compile("MyClass"); // Name of the compiled library (without extension)
|
||||||
|
|
||||||
|
// Link to the Objective-C runtime
|
||||||
|
println!("cargo:rustc-link-lib=objc"); // Link against the Objective-C runtime library
|
||||||
|
|
||||||
|
// Specify the path to the Objective-C header files
|
||||||
|
println!("cargo:include=objc"); // Include directory for headers
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_swift() {
|
||||||
|
// Compile Swift code using `swiftc`
|
||||||
|
println!("cargo:rerun-if-changed=swift/MySwiftClass.swift");
|
||||||
|
let swift_output_dir = "swift";
|
||||||
|
let swift_file = "swift/MySwiftClass.swift";
|
||||||
|
let swift_lib = "libSwiftModule.dylib";
|
||||||
|
|
||||||
|
// Ensure swift directory exists
|
||||||
|
if !Path::new(swift_output_dir).exists() {
|
||||||
|
std::fs::create_dir_all(swift_output_dir).expect("Failed to create Swift output directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
Command::new("swiftc")
|
||||||
|
.args(&[
|
||||||
|
"-emit-library",
|
||||||
|
"-emit-module",
|
||||||
|
"-module-name",
|
||||||
|
"SwiftModule",
|
||||||
|
"-o",
|
||||||
|
swift_lib,
|
||||||
|
swift_file,
|
||||||
|
])
|
||||||
|
.current_dir(swift_output_dir)
|
||||||
|
.status()
|
||||||
|
.expect("Failed to compile Swift code");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link_libraries() {
|
||||||
|
// Link to the compiled C, Objective-C, and Swift libraries
|
||||||
|
println!("cargo:rustc-link-lib=static=example");
|
||||||
|
println!("cargo:rustc-link-lib=objc");
|
||||||
|
println!("cargo:rustc-link-lib=dylib=SwiftModule"); // Link the Swift library
|
||||||
|
println!("cargo:rustc-link-search=native=swift"); // Search path for Swift library
|
||||||
|
}
|
9
c/example.c
Normal file
9
c/example.c
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "example.h"
|
||||||
|
|
||||||
|
int add(int a, int b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_message() {
|
||||||
|
printf("Hello from C!\n");
|
||||||
|
}
|
9
c/example.h
Normal file
9
c/example.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef EXAMPLE_H
|
||||||
|
#define EXAMPLE_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int add(int a, int b);
|
||||||
|
void print_message();
|
||||||
|
|
||||||
|
#endif // EXAMPLE_H
|
8
examples/c.rs
Normal file
8
examples/c.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// examples/c.rs
|
||||||
|
// sudo cargo run --example c --release
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
rust_interop::add_and_print(2, 4); // Call the function from rust_interop
|
||||||
|
}
|
||||||
|
}
|
25
examples/java.rs
Normal file
25
examples/java.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Run the Java command after the build
|
||||||
|
if let Err(e) = run_java_command() {
|
||||||
|
panic!("Failed to run Java command: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn run_java_command() -> std::io::Result<()> {
|
||||||
|
let java_class_path = "./java";
|
||||||
|
let java_library_path = "./target/release";
|
||||||
|
|
||||||
|
let status = Command::new("java")
|
||||||
|
.arg("-cp")
|
||||||
|
.arg(java_class_path)
|
||||||
|
.arg(format!("-Djava.library.path={}", java_library_path))
|
||||||
|
.arg("HelloWorld")
|
||||||
|
.status()?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
panic!("Java execution failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
9
examples/swift.rs
Normal file
9
examples/swift.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use rust_interop::swift::swiftFunction;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
// let result = rust_interop::swift::swiftFunction();
|
||||||
|
let result = swiftFunction();
|
||||||
|
println!("Result from Swift function: {}", result);
|
||||||
|
}
|
||||||
|
}
|
24
extra.txt
Normal file
24
extra.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
javac -version
|
||||||
|
sudo cargo build --release
|
||||||
|
sudo cargo run --example c --release
|
||||||
|
sudo cargo run --example java --release
|
||||||
|
sudo cargo run --example swift --release
|
||||||
|
|
||||||
|
|
||||||
|
This will generate a com/example/MyJavaClass.class file.
|
||||||
|
javac -d . MyJavaClass.java
|
||||||
|
|
||||||
|
javac HelloWorld.java
|
||||||
|
|
||||||
|
javac -h . java/HelloWorld.java
|
||||||
|
java -Djava.library.path=./target/release -cp java HelloWorld
|
||||||
|
|
||||||
|
|
||||||
|
javac -h ./java java/HelloWorld.java
|
||||||
|
cargo build --release
|
||||||
|
java -cp ./java -Djava.library.path=./target/release HelloWorld
|
||||||
|
java -verbose:jni -cp ./java -Djava.library.path=./target/release HelloWorld
|
||||||
|
chmod +x ./target/release/librust_jni_example.dylib
|
||||||
|
|
||||||
|
|
||||||
|
swiftc -emit-library -emit-module -module-name SwiftModule -o libSwiftModule.dylib swift/MySwiftClass.swift
|
BIN
java/HelloWorld.class
Normal file
BIN
java/HelloWorld.class
Normal file
Binary file not shown.
21
java/HelloWorld.h
Normal file
21
java/HelloWorld.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
|
#include <jni.h>
|
||||||
|
/* Header for class HelloWorld */
|
||||||
|
|
||||||
|
#ifndef _Included_HelloWorld
|
||||||
|
#define _Included_HelloWorld
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Class: HelloWorld
|
||||||
|
* Method: callRustFunction
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_HelloWorld_callRustFunction
|
||||||
|
(JNIEnv *, jobject);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
17
java/HelloWorld.java
Normal file
17
java/HelloWorld.java
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// java/HelloWorld.java
|
||||||
|
public class HelloWorld {
|
||||||
|
static {
|
||||||
|
System.loadLibrary("rust_interop");
|
||||||
|
}
|
||||||
|
|
||||||
|
public native void callRustFunction();
|
||||||
|
|
||||||
|
public String getGreeting() {
|
||||||
|
return "Hello from Java!";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
HelloWorld hw = new HelloWorld();
|
||||||
|
hw.callRustFunction();
|
||||||
|
}
|
||||||
|
}
|
14
java/Main.java
Normal file
14
java/Main.java
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// java/Main.java
|
||||||
|
public class Main {
|
||||||
|
static {
|
||||||
|
System.loadLibrary("rust_jni_example");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native void call_java_from_rust();
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Calling Rust function...");
|
||||||
|
call_java_from_rust();
|
||||||
|
System.out.println("Rust function call completed.");
|
||||||
|
}
|
||||||
|
}
|
0
javascript/index.js
Normal file
0
javascript/index.js
Normal file
20
objc/MyClass.h
Normal file
20
objc/MyClass.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// swift/MyClass.h
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Declare functions to be used by Rust
|
||||||
|
void create_object();
|
||||||
|
void call_method();
|
||||||
|
const char* get_message();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface MyClass : NSObject
|
||||||
|
- (void)printMessage;
|
||||||
|
- (NSString *)getMessage;
|
||||||
|
@end
|
35
objc/MyClass.m
Normal file
35
objc/MyClass.m
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// swift/MyClass.m
|
||||||
|
#import "MyClass.h"
|
||||||
|
|
||||||
|
@implementation MyClass
|
||||||
|
|
||||||
|
- (void)printMessage {
|
||||||
|
NSLog(@"Hello from Objective-C!");
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)getMessage {
|
||||||
|
return @"Hello from Objective-C!";
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// C-compatible interface functions
|
||||||
|
static MyClass *myClassInstance = nil;
|
||||||
|
|
||||||
|
void create_object() {
|
||||||
|
myClassInstance = [[MyClass alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
void call_method() {
|
||||||
|
if (myClassInstance) {
|
||||||
|
[myClassInstance printMessage];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* get_message() {
|
||||||
|
if (myClassInstance) {
|
||||||
|
NSString *message = [myClassInstance getMessage];
|
||||||
|
return [message UTF8String];
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
6
objc/objc_wrapper.h
Normal file
6
objc/objc_wrapper.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef OBJC_WRAPPER_H
|
||||||
|
#define OBJC_WRAPPER_H
|
||||||
|
|
||||||
|
void call_objc_function();
|
||||||
|
|
||||||
|
#endif // OBJC_WRAPPER_H
|
7
objc/objc_wrapper.m
Normal file
7
objc/objc_wrapper.m
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#import "objc_wrapper.h"
|
||||||
|
#import "MyClass.h"
|
||||||
|
|
||||||
|
void call_objc_function() {
|
||||||
|
MyClass *obj = [[MyClass alloc] init];
|
||||||
|
[obj helloFromObjectiveC];
|
||||||
|
}
|
5
src/c.rs
Normal file
5
src/c.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// Declare external functions from C
|
||||||
|
extern "C" {
|
||||||
|
pub fn add(a: i32, b: i32) -> i32;
|
||||||
|
pub fn print_message();
|
||||||
|
}
|
188
src/java.rs
Normal file
188
src/java.rs
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
use makepad_android_state::get_java_vm;
|
||||||
|
use makepad_jni_sys::{jint, jobject, JavaVM, _jmethodID, _jobject};
|
||||||
|
use std::{
|
||||||
|
ffi::{CStr, CString},
|
||||||
|
ptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
use makepad_jni_sys as jni_sys;
|
||||||
|
|
||||||
|
static mut _ACTIVITY: jobject = ptr::null_mut();
|
||||||
|
static mut VM: *mut JavaVM = ptr::null_mut();
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn call_java_from_rust() {
|
||||||
|
unsafe {
|
||||||
|
// Get the JavaVM instance
|
||||||
|
if get_java_vm().is_null() {
|
||||||
|
eprintln!("Failed to get JavaVM");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let env = attach_jni_env();
|
||||||
|
|
||||||
|
let class_name = CString::new("HelloWorld").unwrap();
|
||||||
|
let method_name = CString::new("getGreeting").unwrap();
|
||||||
|
let method_sig = CString::new("()Ljava/lang/String;").unwrap();
|
||||||
|
let (obj, method_id) = new_object(env, class_name, method_name, method_sig);
|
||||||
|
|
||||||
|
// let method_name = CString::new("getGreeting").unwrap();
|
||||||
|
// let method_sig = CString::new("()Ljava/lang/String;").unwrap();
|
||||||
|
// let method_id =
|
||||||
|
// (**env).GetMethodID.unwrap()(env, class, method_name.as_ptr(), method_sig.as_ptr());
|
||||||
|
// if method_id.is_null() {
|
||||||
|
// eprintln!("Failed to find getGreeting method.");
|
||||||
|
// detach_current_thread();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// println!("Found getGreeting method.");
|
||||||
|
|
||||||
|
let result = (**env).CallObjectMethod.unwrap()(env, obj, method_id);
|
||||||
|
if result.is_null() {
|
||||||
|
eprintln!("Failed to call getGreeting method.");
|
||||||
|
detach_current_thread();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("Called getGreeting method.");
|
||||||
|
|
||||||
|
let result_str_ptr = (**env).GetStringUTFChars.unwrap()(env, result, ptr::null_mut());
|
||||||
|
if result_str_ptr.is_null() {
|
||||||
|
eprintln!("Failed to convert Java string to Rust string.");
|
||||||
|
detach_current_thread();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result_str = CStr::from_ptr(result_str_ptr)
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
println!("Result from Java: {}", result_str);
|
||||||
|
|
||||||
|
(**env).ReleaseStringUTFChars.unwrap()(env, result, result_str_ptr);
|
||||||
|
|
||||||
|
// Detach the current thread from the JVM
|
||||||
|
detach_current_thread();
|
||||||
|
|
||||||
|
// Note: We're not destroying the JVM here because it's generally not recommended
|
||||||
|
// to destroy the JVM unless you're absolutely sure you want to terminate the entire Java environment.
|
||||||
|
// If you do need to destroy the JVM, you can uncomment the following code:
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Destroy the JVM
|
||||||
|
let destroy_res = (**vm).DestroyJavaVM.unwrap()(vm);
|
||||||
|
if destroy_res != 0 {
|
||||||
|
eprintln!("Failed to destroy JVM.");
|
||||||
|
} else {
|
||||||
|
println!("Destroyed JVM.");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn new_object(
|
||||||
|
env: *mut jni_sys::JNIEnv,
|
||||||
|
class_name: CString,
|
||||||
|
method_name: CString,
|
||||||
|
method_sig: CString,
|
||||||
|
) -> (*mut _jobject, *mut _jmethodID) {
|
||||||
|
let find_class = (**env).FindClass.unwrap();
|
||||||
|
let get_method_id = (**env).GetMethodID.unwrap();
|
||||||
|
let new_object_here = (**env).NewObject.unwrap();
|
||||||
|
|
||||||
|
let class = find_class(env, class_name.as_ptr() as _);
|
||||||
|
if class.is_null() {
|
||||||
|
eprintln!("Failed to find {:?} class.", class_name);
|
||||||
|
detach_current_thread();
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
println!("Found {:?} class.", class_name);
|
||||||
|
|
||||||
|
let method_id = get_method_id(
|
||||||
|
env,
|
||||||
|
class,
|
||||||
|
method_name.as_ptr() as _,
|
||||||
|
method_sig.as_ptr() as _,
|
||||||
|
);
|
||||||
|
if method_id.is_null() {
|
||||||
|
eprintln!("Failed to find constructor method.");
|
||||||
|
detach_current_thread();
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
println!("Found constructor method.");
|
||||||
|
|
||||||
|
let obj = new_object_here(env, class, method_id);
|
||||||
|
if obj.is_null() {
|
||||||
|
eprintln!("Failed to create {:?} object.", class_name);
|
||||||
|
detach_current_thread();
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
println!("Created {:?} object.", class_name);
|
||||||
|
(obj, method_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn detach_current_thread() {
|
||||||
|
// eprintln!("Failed to find constructor method.");
|
||||||
|
let detach_res = (**get_java_vm()).DetachCurrentThread.unwrap()(get_java_vm());
|
||||||
|
if detach_res != 0 {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to detach current thread. Error code: {}. Ensure the thread is properly attached and the JVM state is correct.",
|
||||||
|
detach_res
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("Detached current thread from JVM.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn attach_jni_env() -> *mut jni_sys::JNIEnv {
|
||||||
|
let mut env: *mut jni_sys::JNIEnv = std::ptr::null_mut();
|
||||||
|
let attach_current_thread = (**get_java_vm()).AttachCurrentThread.unwrap();
|
||||||
|
|
||||||
|
let res = attach_current_thread(get_java_vm(), &mut env, std::ptr::null_mut());
|
||||||
|
// assert!(res == 0);
|
||||||
|
if res != 0 || env.is_null() {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to attach current thread or env is null. Error code: {}",
|
||||||
|
res
|
||||||
|
);
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
println!("Attached current thread to JVM.");
|
||||||
|
env
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn test_attach_detach() {
|
||||||
|
unsafe {
|
||||||
|
if get_java_vm().is_null() {
|
||||||
|
eprintln!("Failed to get JavaVM");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = attach_jni_env();
|
||||||
|
|
||||||
|
detach_current_thread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn Java_HelloWorld_callRustFunction(_env: *mut jni_sys::JNIEnv, _obj: jobject) {
|
||||||
|
// Implementation of your native method
|
||||||
|
// println!("Rust function callRustFunction is called from Java!");
|
||||||
|
// Optionally, you can call other Rust functions like call_java_from_rust() here if needed
|
||||||
|
call_java_from_rust();
|
||||||
|
// test_attach_detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "system" fn JNI_OnLoad(vm: *mut JavaVM, _reserved: *const std::ffi::c_void) -> jint {
|
||||||
|
unsafe {
|
||||||
|
VM = vm;
|
||||||
|
}
|
||||||
|
jni_sys::JNI_VERSION_1_6
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn JNI_OnUnload(_vm: *mut JavaVM, _reserved: *const std::ffi::c_void) {
|
||||||
|
// unsafe {
|
||||||
|
// // Optionally, you can add cleanup code here
|
||||||
|
// }
|
||||||
|
}
|
30
src/lib.rs
Normal file
30
src/lib.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//File lib.rs
|
||||||
|
|
||||||
|
// src/lib.rs
|
||||||
|
// src/java.rs
|
||||||
|
// src/rust_interop.rs
|
||||||
|
// src/c.rs
|
||||||
|
// examples/c.rs
|
||||||
|
// examples/java.rs
|
||||||
|
// examples/swift.rs
|
||||||
|
// src/main.rs
|
||||||
|
// src/objc.rs
|
||||||
|
// src/swift
|
||||||
|
// c/example.h
|
||||||
|
// c/example.c
|
||||||
|
// java/HelloWorld.java
|
||||||
|
// java/HelloWorld.class
|
||||||
|
// objc/MyClass.h
|
||||||
|
// objc/MyClass.m
|
||||||
|
// swift/MySwiftClass.swift
|
||||||
|
// swift/SwiftModule.h
|
||||||
|
// swift/module.modulemap
|
||||||
|
// Cargo.toml
|
||||||
|
// build.rs
|
||||||
|
pub mod c;
|
||||||
|
pub mod java;
|
||||||
|
pub mod objc;
|
||||||
|
pub mod rust_interop;
|
||||||
|
pub mod swift;
|
||||||
|
|
||||||
|
pub use rust_interop::add_and_print; // Re-export the function for easier access
|
7
src/objc.rs
Normal file
7
src/objc.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use std::ffi::c_char;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn create_object();
|
||||||
|
pub fn call_method();
|
||||||
|
pub fn get_message() -> *const c_char;
|
||||||
|
}
|
10
src/rust_interop.rs
Normal file
10
src/rust_interop.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// src/rust_interop.rs
|
||||||
|
pub use crate::c::{add, print_message};
|
||||||
|
|
||||||
|
pub fn add_and_print(a: i32, b: i32) {
|
||||||
|
let result = unsafe { add(a, b) };
|
||||||
|
println!("The result of adding {} and {} is: {}", a, b, result);
|
||||||
|
unsafe {
|
||||||
|
print_message();
|
||||||
|
}
|
||||||
|
}
|
8
src/swift.rs
Normal file
8
src/swift.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use libc::c_int;
|
||||||
|
// use std::ffi::CString;
|
||||||
|
// use std::os::raw::c_void;
|
||||||
|
// use std::ptr;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn swiftFunction() -> c_int;
|
||||||
|
}
|
8
swift/MySwiftClass.swift
Normal file
8
swift/MySwiftClass.swift
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// swift/MySwiftClass.swift
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@_silgen_name("swift_function")
|
||||||
|
func swiftFunction() -> Int32 {
|
||||||
|
print("Swift function called")
|
||||||
|
return 42
|
||||||
|
}
|
9
swift/SwiftModule.abi.json
Normal file
9
swift/SwiftModule.abi.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"ABIRoot": {
|
||||||
|
"kind": "Root",
|
||||||
|
"name": "TopLevel",
|
||||||
|
"printedName": "TopLevel",
|
||||||
|
"json_format_version": 8
|
||||||
|
},
|
||||||
|
"ConstValues": []
|
||||||
|
}
|
15
swift/SwiftModule.h
Normal file
15
swift/SwiftModule.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// swift/SwiftModule.h
|
||||||
|
#ifndef SWIFT_MODULE_H
|
||||||
|
#define SWIFT_MODULE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int32_t swiftFunction();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SWIFT_MODULE_H
|
BIN
swift/SwiftModule.swiftdoc
Normal file
BIN
swift/SwiftModule.swiftdoc
Normal file
Binary file not shown.
BIN
swift/SwiftModule.swiftmodule
Normal file
BIN
swift/SwiftModule.swiftmodule
Normal file
Binary file not shown.
BIN
swift/SwiftModule.swiftsourceinfo
Normal file
BIN
swift/SwiftModule.swiftsourceinfo
Normal file
Binary file not shown.
BIN
swift/libSwiftModule.dylib
Executable file
BIN
swift/libSwiftModule.dylib
Executable file
Binary file not shown.
4
swift/module.modulemap
Normal file
4
swift/module.modulemap
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module SwiftModule {
|
||||||
|
header "SwiftModule.h"
|
||||||
|
export *
|
||||||
|
}
|
Loading…
Reference in a new issue