Verknüpfen Sie meine dynamische Rostbibliothek mit meinem Android Proj über NDK Unzufriedene Link -Fehler [geschlossen]Android

Forum für diejenigen, die für Android programmieren
Anonymous
 Verknüpfen Sie meine dynamische Rostbibliothek mit meinem Android Proj über NDK Unzufriedene Link -Fehler [geschlossen]

Post by Anonymous »

Hallo, ich plane, eine null-kenntnis-Proof-basierte Geolocation-Tracking zu implementieren, aber leider ist der ZKP nur als Rust-Bibliotheken erhältlich (wenn ihr dieses ZKP-Zeug nicht als Bibliothek annimmt, die Ihnen hilft, etwas zu beweisen, Sagen Sie dieses Zeug nur für den Kontext). Android -Projektstruktur ist: < /p>

Code: Select all

majorapplication/
|
|-app/
|--src/
|---main/
|----cpp/
|-----CMakeLists.TXT
|-----majorapplication.cpp
|----java/
|----jniLibs/
|-----x86/
|-----x86_64/
|------lib_zkp.so
|------libmajorapplication.so
|-----arm64-v8a/
|-----armeabi-v7a/
|-rustbulletproof(rust project)
|--cargo.toml
|--cbindgen.toml
|--build.rs
|--src/
|---lib.rs(contains the FFI code)

< /code>
Zuerst habe ich die Rust -Bibliothek mit der folgenden Konfiguration geschrieben: < /p>
// cargo.toml

[package]
name = "rustbulletproof"
version = "0.1.0"
edition = "2021"

[dependencies]
bulletproofs = "4.0.0"
curve25519-dalek-ng = "4.1.0"
merlin = "3.0.0"
rand = "0.8.5"
libc = "0.2.169"
geo-types = "0.7.9"
anyhow = "1.0.71"
serde = { version = "1.0", features = ["derive"] }
bincode = "1.3"

[lib]
name = "zkp_proximity"
crate-type = ["cdylib"]  # For FFI with Android

[build-dependencies]
cbindgen = "0.26"

< /code>
// cbindgen.toml :

language = "C++"
include_guard = "BULLETPROOFS_GEO_H"
namespace = "bulletproofs_geo"

[defines]
"target_os = android" = "ANDROID"

[export]
prefix = "BPG_"
include = ["ProofData"]

[parse]
parse_deps = true
include = ["bulletproofs", "curve25519_dalek_ng","merlin","rand","libc","geo-types","anyhow","serde","bincode"]

< /code>
// build.rs

use std::env;

fn main() {
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let config = cbindgen::Config::from_file("cbindgen.toml")
.expect("Unable to find cbindgen.toml");

cbindgen::Builder::new()
.with_crate(crate_dir)
.with_config(config)
.generate()
.expect("Unable to generate bindings")
.write_to_file("include/bulletproofs_geo.h");
}
< /code>
// lib.rs

use std::mem;
mod distance;
mod prover;

#[repr(C)]
pub struct ProofData {
proof_bytes: *const u8,
proof_len: usize,
ristretto_bytes: *const u8,
ristretto_len: usize,
bp_gens_capacity: usize,
bp_gens_party_capacity: usize,
// We'll serialize these into bytes for FFI
pedersen_bytes: [u8; 64], // 2 compressed points, 32 bytes each
}

#[no_mangle]
pub extern "C" fn start_proof(x1: f64, y1: f64, x2: f64, y2: f64) -> ProofData {
let c1 = geo_types::Coord { x: x1, y: y1 };
let c2 = geo_types::Coord { x: x2, y: y2 };
let mut distance: u64 = 0;

if let Ok(d) = distance::distance_from_coords(&c1, &c2) {
distance = (d * 1000.0) as u64;
}

let range_proof_res_obj = prover::fun_prover(distance);
let (pc_gens, bp_gens, proof_result) = range_proof_res_obj;

match proof_result {
Ok((proof, ristretto)) => {
let proof_bytes = proof.to_bytes();
let ristretto_bytes = bincode::serialize(&ristretto).unwrap();

// Convert Pedersen generators to bytes
let mut pedersen_bytes = [0u8; 64];
pedersen_bytes[..32].copy_from_slice(&pc_gens.B.compress().to_bytes());
pedersen_bytes[32..].copy_from_slice(&pc_gens.B_blinding.compress().to_bytes());

let proof_ptr = proof_bytes.as_ptr();
let proof_len = proof_bytes.len();
let ristretto_ptr = ristretto_bytes.as_ptr();
let ristretto_len = ristretto_bytes.len();

// Prevent deallocation
mem::forget(proof_bytes);
mem::forget(ristretto_bytes);

ProofData {
proof_bytes: proof_ptr,
proof_len,
ristretto_bytes: ristretto_ptr,
ristretto_len,
bp_gens_capacity: bp_gens.gens_capacity,
bp_gens_party_capacity: bp_gens.party_capacity,
pedersen_bytes,
}
}
Err(_) =>  ProofData {
proof_bytes: std::ptr::null(),
proof_len: 0,
ristretto_bytes: std::ptr::null(),
ristretto_len: 0,
bp_gens_capacity: 0,
bp_gens_party_capacity: 0,
pedersen_bytes: [0u8; 64],
}
}
}

#[no_mangle]
pub extern "C"  fn free_proof_data(data: ProofData) {
if !data.proof_bytes.is_null() {
unsafe {
Vec::from_raw_parts(
data.proof_bytes as *mut u8,
data.proof_len,
data.proof_len
);
}
}

if !data.ristretto_bytes.is_null() {
unsafe {
Vec::from_raw_parts(
data.ristretto_bytes as *mut u8,
data.ristretto_len,
data.ristretto_len
);
}
}
}

< /code>
Now I built the above code to .so files using the following command :
cargo ndk -t x86 -t x86_64 -t arm64-v8a -t armeabi-v7a -o ./../app/src/main/jniLibs build --release

Dies schließt den Rost -Teil:
Verwenden Sie jetzt das NDK von Android I, den ich mit der folgenden Konfiguration erstellt hat:
// app/build.gradle.kts

import com.android.sdklib.devices.Abi

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}

android {
namespace = "com.example.majorapplication"
compileSdk = 35

defaultConfig {
applicationId = "com.example.majorapplication"
minSdk = 29
targetSdk = 35
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

sourceSets {
getByName("main") {
jniLibs {

srcDirs("src/main/jniLibs")
}
}
}

ndk {
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")

}

}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
debug {
// Enable debugging for native code
isJniDebuggable = true
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"

}
}
ndkVersion = rootProject.extra["ndkVersion"] as String

}

dependencies {

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
implementation(libs.play.services.location)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}

< /code>
// CMakeLists.TXT

cmake_minimum_required(VERSION 3.22.1)
project("majorapplication")

set(RUST_LIB_NAME zkp_proximity)
set(JNI_LIB_NAME majorapplication)

# Set the path relative to CMakeLists.txt location
set(RUST_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

message(STATUS "ANDROID_ABI: ${ANDROID_ABI}")
message(STATUS "Looking for library at: ${RUST_LIB_DIR}/${ANDROID_ABI}/lib${RUST_LIB_NAME}.so")

add_library(${CMAKE_PROJECT_NAME} SHARED
majorapplication.cpp)
# Add Rust library - use consistent naming without 'lib' prefix in target name
add_library(${RUST_LIB_NAME} SHARED IMPORTED)

if(NOT EXISTS "${RUST_LIB_DIR}/lib${RUST_LIB_NAME}.so")
message(FATAL_ERROR "Rust library not found at: ${RUST_LIB_DIR}/lib${RUST_LIB_NAME}.so")
endif()

set_target_properties(${RUST_LIB_NAME} PROPERTIES
IMPORTED_LOCATION "${RUST_LIB_DIR}/lib${RUST_LIB_NAME}.so"
)

#set_target_properties(${RUST_LIB_NAME} PROPERTIES
# IMPORTED_LOCATION ${RUST_LIB_DIR}/lib${RUST_LIB_NAME}.so)

# Add JNI library

include_directories(${CMAKE_SOURCE_DIR}/../../../../rustbulletproof/include)

# Link against ${RUST_LIB_NAME} instead of libzkp_proximity
target_link_libraries(

${CMAKE_PROJECT_NAME}
${RUST_LIB_NAME}
android
log)

< /code>
// majorapplication.cpp

#include
#include
#include
#include
#include "bulletproofs_geo.h" // Your generated header

extern "C" {
JNIEXPORT jobject JNICALL
Java_com_example_majorapplication_BulletproofsBinding_generateProof(
JNIEnv *env,
jobject /* this */,
jdouble x1,
jdouble y1,
jdouble x2,
jdouble y2) {

// Call the Rust function
bulletproofs_geo::BPG_ProofData proof_data = bulletproofs_geo::start_proof(x1, y1, x2, y2);

// Create byte arrays for proof and commitment
jbyteArray proofBytes = env->NewByteArray(proof_data.proof_len);
jbyteArray ristrettoBytes = env->NewByteArray(proof_data.ristretto_len);
jbyteArray pedersenBytes = env->NewByteArray(64); // Fixed size for Pedersen gens

// Copy data to Java byte arrays
env->SetByteArrayRegion(proofBytes, 0, proof_data.proof_len,
reinterpret_cast(proof_data.proof_bytes));
env->SetByteArrayRegion(ristrettoBytes, 0, proof_data.ristretto_len,
reinterpret_cast(proof_data.ristretto_bytes));
env->SetByteArrayRegion(pedersenBytes, 0, 64,
reinterpret_cast(proof_data.pedersen_bytes));

// Get the ProofResult class
jclass proofResultClass = env->FindClass("com/example/majorapplication/ProofResult");
if (proofResultClass == nullptr) {
return nullptr;
}

// Get the constructor
jmethodID constructor = env->GetMethodID(proofResultClass, "",
"([B[B[BJJ)V");
if (constructor == nullptr) {
return nullptr;
}

// Create and return the ProofResult object
jobject result = env->NewObject(proofResultClass, constructor,
proofBytes,
ristrettoBytes,
pedersenBytes,
(jlong)proof_data.bp_gens_capacity,
(jlong)proof_data.bp_gens_party_capacity);

// Free the native memory
free_proof_data(proof_data);

return result;
}
}

< /code>
This concludes the JNI part
Now lets tackle the issue of this post:
inside the src directory of the android app module I have a class which uses the shared library :
// BulletproofBindings.kt :

package com.example.majorapplication

import android.util.Log

class BulletproofsBinding {
companion object {
init {
try {
System.loadLibrary("majorapplication")
} catch (e: UnsatisfiedLinkError) {
Log.e("BulletproofsBinding", "Error loading library: ${e.message}")
throw e
}
}
}

private external fun generateProof(x1: Double, y1: Double, x2: Double, y2: Double): ProofResult?

fun generateProofForCoordinates(
lat1: Double,
lon1: Double,
lat2: Double,
lon2: Double
): ProofResult? {
return generateProof(lat1, lon1, lat2, lon2)
}
}

< /code>
proofresult.kt :

package com.example.majorapplication
data class ProofResult(
val proofBytes: ByteArray,
val ristrettoBytes: ByteArray,
val pedersenBytes: ByteArray,
val bpGensCapacity: Long,
val bpGensPartyCapacity: Long
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as ProofResult

if (!proofBytes.contentEquals(other.proofBytes)) return false
if (!ristrettoBytes.contentEquals(other.ristrettoBytes)) return false
if (!pedersenBytes.contentEquals(other.pedersenBytes)) return false
if (bpGensCapacity != other.bpGensCapacity) return false
if (bpGensPartyCapacity != other.bpGensPartyCapacity) return false

return true
}

override fun hashCode(): Int {
var result = proofBytes.contentHashCode()
result = 31 * result + ristrettoBytes.contentHashCode()
result = 31 * result + pedersenBytes.contentHashCode()
result = 31 * result + bpGensCapacity.hashCode()
result = 31 * result + bpGensPartyCapacity.hashCode()
return result
}
}

< /code>
Now the issue is whenever I build the app it is executing properly, the .so files are being copied into the jni libs folders properly as I analysed through the apk inspector ,but when I run it it is throwing an UnsatisfiedLink error :
// Output in logcat when app is built :

BulletproofsBinding com.example.majorapplication E Error loading library: dlopen failed:
library "C:/Users/mahes/AndroidStudioProjects/MajorApplication/app/src/main/cpp/../jniLibs/x86_64/libzkp_proximity.so" not found:
needed by /data/app/~~-72oLmY0_i-Hq9cSQjWwCg==/com.example.majorapplication-qlCmojO1J_C3_1icpRzu4g==/base.apk!/lib/x86_64/libmajorapplication.so
in namespace classloader-namespace
2025-02-23 17:22:44.529 13474-13474 AndroidRuntime com.example.majorapplication D Shutting down VM
2025-02-23 17:22:44.531 13474-13474 AndroidRuntime com.example.majorapplication E FATAL EXCEPTION: main
Process: com.example.majorapplication, PID: 13474
java.lang.UnsatisfiedLinkError: dlopen failed:
library "C:/Users/mahes/AndroidStudioProjects/MajorApplication/app/src/main/cpp/../jniLibs/x86_64/libzkp_proximity.so" not found:
needed by /data/app/~~-72oLmY0_i-Hq9cSQjWwCg==/com.example.majorapplication-qlCmojO1J_C3_1icpRzu4g==/base.apk!/lib/x86_64/libmajorapplication.so
in namespace classloader-namespace
at java.lang.Runtime.loadLibrary0(Runtime.java:1077)
at java.lang.Runtime.loadLibrary0(Runtime.java:998)
at java.lang.System.loadLibrary(System.java:1661)
at com.example.majorapplication.BulletproofsBinding.(BulletproofsBinding.kt:9)
at com.example.majorapplication.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:29)
at com.example.majorapplication.ComposableSingletons$MainActivityKt$lambda-1$1.invoke(MainActivity.kt:24)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke

< /code>
pls help me I am struck in this from past 2 days.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post