2010-11-12 20 views
7

Tengo un método en C++ que tiene una matriz de dobles como argumento. Estoy llamando a este método desde Java y necesito pasar una serie de dobles. La rutina C++ lee y modifica los valores de la matriz y necesito esos valores actualizados en Java. ¿Cómo hago esto?¿Cómo paso las matrices de Java a C++ usando Swig?

Por ejemplo, tomar la C++ rutina:

void myMethod(double *values, int size) { 
    for (int i=0; i < size; i++) { 
     values[i] = 2*values[i]; 
    } 
} 

Y el código de Java:

double[] values = { 1.3, 1.1 }; 
myMethod(values,values.length); 
System.out.println(values[0]); // prints 2.6 

supongo que una llamada a myMethod no se puede hacer como la llamada anterior ... o puede ? Y lo que es necesario en Swig para que esto funcione. Si no puedo hacer una llamada como la de arriba, ¿cómo obtengo mis valores para el código de C++?

+1

SWIG es respondida por mi respuesta. El resto de las respuestas discuten alternativas. –

+0

Sí, muchas gracias Andy! Comprende mi pregunta y me dio una respuesta muy adecuada ... Todavía estoy buscando más respuestas. Estoy particularmente interesado en lo que hace la mayoría de las personas, ya que esta situación debe aparecer todo el tiempo. ¿La mayoría de la gente usa Swig 2? ¿La mayoría de las personas escribe sus propios mapas de tipos? Ambos me parecen extremos. – Jason

+0

Si tengo que copiar la matriz en C++ manualmente, está bien. Si puedo asignar una matriz en C++ y tengo que usar métodos especiales para acceder a los valores en Java, está bien. ¿Qué hace la mayoría de las personas en casos como este? – Jason

Respuesta

6

¡Utilice carrays.i!

Ver Swig docs on carrays

%include carrays.i 
%array_functions(double, double_array) 

Estas dos líneas crean el código siguiente en mi módulo:

public static SWIGTYPE_p_double new_double_array(int nelements) { 
    long cPtr = SimulatorModuleJNI.new_double_array(nelements); 
    return (cPtr == 0) ? null : new SWIGTYPE_p_double(cPtr, false); 
    } 

    public static void delete_double_array(SWIGTYPE_p_double ary) { 
    SimulatorModuleJNI.delete_double_array(SWIGTYPE_p_double.getCPtr(ary)); 
    } 

    public static double double_array_getitem(SWIGTYPE_p_double ary, int index) { 
    return SimulatorModuleJNI.double_array_getitem(SWIGTYPE_p_double.getCPtr(ary), index); 
    } 

    public static void double_array_setitem(SWIGTYPE_p_double ary, int index, double value) { 
    SimulatorModuleJNI.double_array_setitem(SWIGTYPE_p_double.getCPtr(ary), index, value); 
    } 

que me permite utilizar matrices en Java C ... esto resuelve mis necesidades y es el La mejor solución para mi problema. ¡Gracias a todos por sus respuestas!

+0

Gracias por publicar un enfoque más fácil. Creo que deberías aceptar tu propia respuesta. El enlace SWIG 2.0 para carrays está en http://www.swig.org/Doc2.0/SWIGDocumentation.html#Library_carrays. –

+0

¿Es esta la manera más rápida? Supongo que debe llamar a SWIGTYPE_p_double con la cantidad de elementos en su matriz de Java, luego copie cada elemento a la nueva matriz, luego realice el procesamiento en C++ en la nueva matriz y luego vuelva a copiar cada elemento en la matriz de Java. ¿Hay alguna manera de hacer acceso directo a la memoria y simplemente pasar un puntero entre los dos idiomas? ¿O estas operaciones de copia extra son la única forma de hacerlo debido a la diferencia en la administración de la memoria entre Java y Cxx? – LaserJesus

0

Si es sólo que un solo método, reescribirlo. Si tiene una base de código C++ (mucho) más grande que necesita portar, use JNI (o la más simple JNA). Esto agrega un poco de sobrecarga de código, pero es factible.

+0

Um ... eso es exactamente lo que estoy haciendo ... usando JNI porque es una gran base de código. Así que elegí usar Swig para crear los contenedores JNI ... ya que Swig es _much_ más simple. – Jason

1

SWIG typemaps debe permitir esto. La documentación de SWIG 2.0 muestra esto example in Python.

Con Java, usaría el código JNI dentro de su mapa de tipos SWIG. JNI proporciona métodos Get/ReleaseArrayElements. Supongo que podría obtener una matriz nativa en un typemap(in), luego libérela en un typemap(argout).

Otro enfoque sería copiar su matriz en un std :: vector, utilizando el mapa de tipos SWIG existente en std_vector.i.

+0

¡Esta es una gran respuesta! ¡Gracias! Puedo usar esta solución. Pero la primera parte (escribir mi propio mapa de tipos) es compleja y la segunda parte requiere Swig 2. En este momento, creo que debe haber una solución más simple ... y no me importa escribir algún código para copiar la matriz en C. Voy a actualizar mis preguntas ... ver la actualización en la parte superior. – Jason

Cuestiones relacionadas