Pasar matriz de bytes de Unity a Android (C++) para modificar
– UnityAssets3Free
bienvenido , soy josel luis y esta vez os traigo
nueva pregunta
Estoy tratando de usar una biblioteca nativa para modificar el contenido de una matriz de bytes (en realidad, matriz uint16). Tengo la matriz en Unity (C#) y una biblioteca nativa en C++.
Probé algunas cosas, lo mejor que pude obtener es llamar con éxito al código nativo y poder devolver un valor booleano a C#. El problema surge cuando paso una matriz y la cambio en C++. No importa lo que haga, la matriz aparece sin cambios en C#.
Esto es lo que tengo en el lado de Unity:
// In Update().
using (AndroidJavaClass processingClass = new AndroidJavaClass(
"com.postprocessing.PostprocessingJniHelper"))
if (postprocessingClass == null)
Debug.LogError("Could not find the postprocessing class.");
return;
short[] dataShortIn = ...; // My original data.
short[] dataShortOut = new short[dataShortIn.Length];
Buffer.BlockCopy(dataShortIn, 0, dataShortOut, 0, dataShortIn.Length);
bool success = postprocessingClass.CallStatic<bool>(
"postprocess", TextureSize.x, TextureSize.y,
dataShortIn, dataShortOut);
Debug.Log("Processed successfully: " + success);
El proyecto de Unity tiene un postprocessing.aar en Plugins/Android y está habilitado para Android plataforma de construcción. Tengo una capa JNI en Java (que se llama con éxito):
public final class PostprocessingJniHelper
// Load JNI methods
static
System.loadLibrary("postprocessing_jni");
public static native boolean postprocess(
int width, int height, short[] inData, short[] outData);
private PostprocessingJniHelper()
El código Java anterior llama a este código en C++.
extern "C" {
JNIEXPORT jboolean JNICALL POSTPROCESSING_JNI_METHOD_HELPER(postprocess)(
JNIEnv *env, jclass thiz, jint width, jint height, jshortArray inData, jshortArray outData)
jshort *inPtr = env->GetShortArrayElements(inData, nullptr);
jshort *outPtr = env->GetShortArrayElements(outData, nullptr);
jboolean status = false;
if (inPtr != nullptr && outPtr != nullptr)
status = PostprocessNative(
reinterpret_cast<const uint16_t *>(inPtr), width, height,
reinterpret_cast<uint16_t *>(outPtr));
env->ReleaseShortArrayElements(inData, inPtr, JNI_ABORT);
env->ReleaseShortArrayElements(outData, outPtr, 0);
return status;
Función principal de C++ PostprocessNative
también parece llamarse correctamente (verificado por el valor de retorno), pero cualquier cambio en data_out no se refleja en Unity.
bool PostprocessNative(const uint16_t* data_in, int width,
int height, uint16_t* data_out)
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
data_out[x + y * width] = 10;
// Changing the return value here is correctly reflected in C#.
return false;
Espero todos los valores del corto[] para ser 10, pero son lo que eran antes de llamarse JNI.
¿Es esta una forma correcta de pasar una serie de cortos de Unity a C++ para su modificación?
2 respuestas 2
Primero, no proporcionó ninguna información sobre su configuración. ¿Cuál es su script backend: Mononucleosis infecciosa o IL2CPP?
Segundo, ¿por qué no llamas? C++ código directamente desde C#?
1) Vamos para: [File] > [build Settings] > [Player Settings] > [Player] y llama [Allow ‘unsafe’ Code] propiedad.
dos) Después de compilar la biblioteca, copie los archivos .so de salida en el Activos/Complementos/Android directorio en su proyecto de Unity.
Código C#:
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using System;
public class CallNativeCode : MonoBehaviour
[DllImport("NativeCode")]
unsafe private static extern bool PostprocessNative(int width, int height, short* data_out);
public short[] dataShortOut;
public Text TxtOut;
public void Update()
dataShortOut = new short[100];
bool o = true;
unsafe
fixed (short* ptr = dataShortOut)
o = PostprocessNative(10, 10, ptr);
TxtOut.text = "Function out: " + o + " Array element 0: " + dataShortOut[0];
Código C++:
#include <stdint.h>
#include <android/log.h>
#define LOG(...) __android_log_print(ANDROID_LOG_VERBOSE, "HamidYusifli", __VA_ARGS__)
extern "C"
bool PostprocessNative(int width, int height, short *data_out)
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
data_out[x + y * width] = 10;
LOG("Log: %d", data_out[0]);
// Changing the return value here is correctly reflected in C#.
return false;
GetShortArrayElements
puede arreglar la matriz de Java en la memoria o devolver una copia de los datos. Entonces deberías llamar ReleaseShortArrayElements
cuando haya terminado de usar los punteros.
env->ReleaseShortArrayElements(inData, inPtr, JNI_ABORT); // free the buffer without copying back the possible changes
env->ReleaseShortArrayElements(outData, outPtr, 0); // copy back the content and free the buffer
nota: si aun no se resuelve tu pregunta por favor dejar un comentario y pronto lo podremos de nuevo , muchas gracias
sin mas,espero que te funcione