2016-08-09 22 views
16

Mam dll C++, który chcę użyć w Unity, eksportując funkcje do C#. Projekt Unity działa na urządzeniach z Androidem, a kod C++ korzysta z java. Aby zainicjować C++ trzeba najpierw wywołać następującą funkcję:Uzyskiwanie poprawnego wskaźnika JNIEnv

void api_initialize(JNIEnv* env, jobject* app_context, jobject* class_loader) { 

    JavaVM* vm = nullptr; 
    env->GetJavaVM(&vm); 
    if (!vm) { 
     return; 
    } 

    //Do other proprietary things 
} 

w jedności mam następujące eksportowane funkcja dll

[DllImport (dllName)] 
    private static extern void api_initialize (IntPtr java_env, IntPtr app_context, IntPtr class_loader); 

Moje pytanie brzmi Jak mogę uzyskać wskaźnik JNIEnv w moim C# klasa, która następnie przechodzi jako parametr do tej funkcji?

Nie jestem twórcą tego API i nie mam dostępu do jego modyfikacji, więc muszę uzyskać JavaVM z JNIEnv, a nie na odwrót.

+0

wierzę, że można znaleźć odpowiedź tutaj-> http://stackoverflow.com/questions/21951711/how-to-pass-a-jni-c-sharp-class-into-java- or-handle-this- lub stwórz swój własny wywołanie java za pomocą dokumentacji Oracle -> situationhttp: //docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp715 W każdym razie to bardzo dobre pytanie. – Cabrra

Odpowiedz

3

Chyba nie ma sposobu, można to zrobić (może tam być, ale nie widziałem go jeszcze), ponieważ ten typ NDK calls wymagane owijanie wokół java więc chciałbym celem jest inne rozwiązanie, które używają Java jako intermediate dla wywołań C#, a następnie można redirect to połączenie z NDK code z java.

using UnityEngine; 
using System.Collections; 
using System.IO; 

#if UNITY_ANDROID 
public class JavaCallPlugin { 

    // Avoid invalid calls 
    public static void initiateNDK() { 
    if (Application.platform != RuntimePlatform.Android) 
      return; 

    var pluginClass = 
     new AndroidJavaClass("com.package.class.UnityJavaDelegate"); 
    AndroidJavaObject plugin = 
     pluginClass.CallStatic<AndroidJavaObject>("obj"); 
    return plugin.Call("javaCallToNDK"); 
    } 
} 
#endif 

A w pliku java zrobić

package com.package.class; 

import android.content.ContentValues; 
import android.content.Intent; 
import android.os.Environment; 

public class UnityJavaDelegate{ 
    private static UnityJavaDelegate obj; 

    // define function call to your NDK method with native keyword 
    private native void api_initialize(); 

    static { 
    System.loadLibrary("yourlibraryname"); // setup your ndk lib to use 
    } 

    public static UnityJavaDelegate getObj() { 
    if(m_instance == null) 
     obj= new UnityJavaDelegate(); 
    return obj; 
    } 

    private UnityJavaDelegate(){ 
    } 

    public void javaCallToNDK(){ 
    // this call may not work because i haven't passed class 
    // loader TO NDK before, if not then you should try links 
    // at the bottom of the post to know how to pass customize 
    // as parameter to NDK. 

    // put your call to NDK function here 
    api_initialize(this.getClass().getClassLoader()); 
    } 
} 

Kiedy deklarujesz natywną metodę, javah automatycznie wygenerować definicję połączenia NDK z javaEnv i jobject jako parametr tak myślę, trzeba tylko przejść ładującego klasy tutaj. Możesz wypróbować te linki link i this, aby uzyskać więcej wyjaśnień.

Good Luck. Hope To pomoże.

+1

To pomogło, a to działa! Potwierdziłem przy realizacji. – Maestro

2

Myślę, że możesz stworzyć inną natywną wtyczkę, która da ci JNIEnv.

Plugins for Android

Podsumowując ten artykuł należy spróbować coś takiego (nietestowanego kodu pseudo):

JavaVM* g_JVM; // JavaVM is valid for all threads, so just save it globally 

extern "C" { 
    JNIEnv* GetJniEnv(); 
} 

// The VM calls JNI_OnLoad when the native library is loaded 
jint JNI_OnLoad(JavaVM* vm, void* reserved) { 
    g_JVM = vm; 
    return JNI_VERSION_1_6; 
} 

// The JNI interface pointer (JNIEnv) is valid only in the current thread. 
JNIEnv* GetJniEnv() { 
    JNIEnv* jni_env = 0; 
    g_JVM->AttachCurrentThread(&jni_env, 0); 
    return jni_env; 
} 

Następnie w C#

[DllImport ("PluginName")] 
private static extern IntPtr GetJniEnv(); 
+0

Myślę, że JNI_OnLoad jest wywoływany tylko wtedy, gdy moduł Java wyraźnie żąda załadowania biblioteki (System.loadLibrary). – Maestro

Powiązane problemy