Buscando una buena forma de llamar a Java C++

Parece que la mayoría de la documentación o de auxiliar de bibliotecas relacionadas con JNI (Java Native Interface) se ocupan de llamar a código nativo de Java. Este parece ser el principal uso de ella, aunque es capaz de más.

Quiero principalmente para trabajar en la dirección opuesta: modificar una existente (bastante grande) portable programa de C++ mediante la adición de algunas bibliotecas de Java a ella. Por ejemplo, yo quiero hacer es llamar a bases de datos a través de JDBC, o de la cola de mensajes a través de los sistemas de JMS, o enviar correos electrónicos, o llamar a mi propia las clases de Java, etc. Pero con la cruda JNI esto es bastante desagradable y propenso a errores.

Así que ideal sería escribir código C++ que puede llamar a las clases de Java como fácilmente como C++/CLI, puede llamar a clases CLR. Algo así como:

using namespace java::util::regex; //namespaces mapped

Pattern p = Pattern.compile("[,\\s]+");

array<java::lang::String> result = 
    p.split("one,two, three   four ,  five");

for (int i=0; i < result.length(); i++)
    std::cout << result[i] << std::endl;

De esta manera, yo no tendría que manualmente hacer el trabajo de obtener el IDENTIFICADOR de método, pasando el nombre y la extraña firma cadenas, y deben ser protegidas de la programación de los errores causados por la libre Api para llamar a los métodos. De hecho parecería mucho como el equivalente de Java.

NB. TODAVÍA ESTOY HABLANDO SOBRE EL USO DE JNI! Como la tecnología subyacente es perfecto para mis necesidades. Es «en proceso» y altamente eficiente. No quiero ejecutar Java en un proceso independiente y hacer llamadas RPC a ella. JNI sí está bien. Yo sólo quiero una agradable interfaz.

No tendría que ser una herramienta de generación de código para hacer equivalentes las clases de C++, espacios de nombres, métodos, etc. para que coincida exactamente con lo que se expone por un conjunto de clases Java que especifique. El generado por las clases de C++ sería:

  • Tienen funciones miembro que acepte de forma similar envuelto versiones de sus parámetros y, a continuación, hacer lo que sea necesario JNI vudú para hacer la llamada.
  • Envoltura de los valores de retorno de la misma manera, así que puedo cadena de llamadas de una manera natural.
  • Mantener cada clase estática caché de método de Identificadores para evitar mirar hacia arriba cada vez.
  • Estar totalmente seguro para subprocesos, portátiles, de código abierto.
  • Comprobar automáticamente si hay excepciones después de cada llamada al método y producir una ets excepción de C++.
  • También trabajo para cuando estoy escribiendo métodos nativos en la habitual JNI manera, pero tengo que llamar a otro código Java.
  • La matriz debe trabajar totalmente constantemente entre tipos primitivos y clases.
  • Sin duda necesita algo como global para envolver referencias en cuando que necesitan para sobrevivir fuera de un local marco de referencia – de nuevo, debería funcionar de la misma para todos los de la matriz/referencias a objetos.

Hace libre, de código abierto, biblioteca portátil/herramienta de existir o estoy soñando?

Nota: he encontrado esta pregunta ya existente pero el OP en ese caso no era tan exigente de la perfección como estoy siendo…

Actualización: un comentario sobre el TRAGO me llevó a esta pregunta anterior, lo que parece indicar que se trata principalmente de la dirección opuesta y así no haría lo que yo quiero.

IMPORTANTE

  • Se trata de ser capaz de escribir código C++ que manipula Java clases y objetos, y no a la inversa (véase el título!)
  • Ya sé que JNI existe (vea la pregunta!) Pero el código a mano para la JNI Api es innecesariamente detallado, repetitivo y propenso a errores, no comprobados en tiempo de compilación, etc. Si desea almacenar en caché el método de los Identificadores y los objetos de la clase es aún más detallado. Quiero generar automáticamente C++ clases de contenedor que tener cuidado de todo lo que para mí.

Actualización: he empezado a trabajar en mi propia solución:

https://github.com/danielearwicker/cppjvm

Si este ya existe, por favor hágamelo saber!

NB. Si usted está considerando el uso de este en su propio proyecto, se siente libre, pero ten en cuenta que ahora el código es de un par de horas, y yo sólo escribió tres muy unstrenuous pruebas hasta el momento.

  • Hay LÁMPARA a pesar de que yo sólo se utiliza para C y Python … hace mucho tiempo.
  • Ver actualización: TRAGO al parecer no hacerlo.
  • en el que el compilador/intérprete desea ejecutar su programa, C o Java? Si Java, la inversa no es posible el uso de JNI.
  • He añadido trago a las etiquetas, en caso de que alguien puede aclarar.
  • No entiendo tu pregunta: quiero ejecutar el C++ partes en compilados de forma nativa en C++ (como de costumbre) y el Java partes en la JVM, y para conectar los dos con JNI/invocación. No quiero hacer manualmente todos los JNI tonterías.
  • gcc.gnu.org/onlinedocs/gcj/About-CNI.html ?
  • CNI es una característica de GCJ, que es un compilador para un subconjunto de Java, el apoyo a un subconjunto de las bibliotecas de Java. Quiero usar la 3ª parte de las bibliotecas Java que se ejecuta en un verdadero apoyado implementación de Java.
  • Earwicker – Sí, eso ya existe, véase mi respuesta a continuación.

10 Kommentare

  1. 16

    Sí, existen herramientas que hacer exactamente esto-generar envoltorios de C++ para las clases de Java. Esto hace que el uso de APIs de Java, en C++, más transparente y agradable, con un menor costo y riesgo.

    El que he usado la mayoría es JunC++iónico. Es madura, potente y estable. El autor principal es muy bonito, y muy sensible. Por desgracia, es un producto comercial, y caro.

    Jace gratuita, es una herramienta de código abierto con una licencia BSD. Han pasado años desde la última vez que jugó con jace. Parece que no hay todavía algunos en activo desarrollo. (Todavía me acuerdo de la USENET post por el autor original, hace más de una década, solicitando básicamente la misma pregunta que te estás preguntando.)

    Si usted necesita para apoyar las devoluciones de llamada de Java a C++, es útil para definir las clases de C++ que implementa las interfaces Java. Al menos JunC++iónico permite pasar esas clases de C++ a Java métodos que toman las devoluciones de llamada. La última vez que traté de jace, no apoyo esto, pero eso fue hace siete años.

    • Gracias. Veo desde el Jace de origen que se convierte cada referencia en un mundial! Esto no es una gran idea. La JNI deliberadamente hace que una opción: globals ser más pesado que el de los locales, y la gran mayoría de las variables en un programa real son locales. No hay necesidad para los habitantes de ser «liberados» en un destructor como la JVM toma el cuidado de él. Sólo se necesita una RAII clase para encapsular PushLocalFrame/PopLocalFrame. ¿Qué actitud tiene JunC++iónico tomar para que?
    • Por CIERTO con mi búsqueda de Google para los términos C++ Java JNI Wrapper, ahora veo que JunC++iónico está en la página 22 de los resultados! No ha detectado Jace todavía…
    • JunC++iónico sería en la página 1, si la búsqueda se basa en la calidad. No tengo acceso a JunC++iónico ahora. Me imagino global de las referencias son necesarias en algunos casos y suficiente para los demás, pero eso es sólo una conjetura. Voy a ver si puedo conseguir el autor para responder.
    • Alex Krapf la respuesta por debajo de direcciones global/local referencias.
  2. 8

    Soy uno de los prinicpal arquitectos para Codemesh del lenguaje de integración de productos, incluyendo JunC++iónico. Hemos estado haciendo este tipo de integración desde 1999 y funciona realmente bien. El mayor problema no es la JNI parte. JNI es tedioso y difícil de depurar, pero una vez que lo haga, que en su mayoría sólo se mantiene trabajando. Cada ahora y entonces, obtendrá roto por una JVM o una actualización del sistema operativo y, a continuación, usted tiene que ajustar su producto, pero en general es estable.

    El mayor problema es el tipo de sistema de asignación y los trade-offs entre la usabilidad y la solución específica. Que el estado, por ejemplo, que a usted no le gusta el hecho de que JACE trata a todas las referencias de objeto como globales. Hacemos lo mismo (con algunos portillos de escape) porque resulta que este es el comportamiento que funciona mejor para el 95% de los clientes, incluso si le duele el rendimiento. Si vas a publicar una API o un producto, usted tiene que elegir los valores predeterminados que hacer que las cosas funcionen para la mayoría de la gente. Recogiendo referencias locales como la opción por defecto sería un error debido a que más y más personas están escribiendo aplicaciones multiproceso, y una gran cantidad de APIs de Java que la gente quiere para el uso de otros idiomas son intrínsecamente multiproceso con asincrónica devoluciones de llamada y el como.

    También hemos descubierto que usted realmente desea dar a la gente una interfaz gráfica de usuario basada en el generador de código para crear la integración de la especificación. Una vez que haya especificado para ello, se utiliza la versión CLI para integrarla en la nightly build.

    Buena suerte con su proyecto. Es un montón de trabajo para obtener el derecho. Pasamos varios años en esto y todavía estamos haciendo mejor regularmente.

    • Gracias. Re: la elección razonable de los valores predeterminados, estoy totalmente de acuerdo – es la cosa más importante sobre el diseño de la OMI. Para mi actual proyecto, teniendo la opción de utilizar los locales será importante, y compartido de datos va a ser muy minoritario, así que me voy para java::lang::String y global<java::lang::String> como la sintaxis para los locales y globales, respectivamente.
  3. 4

    Tenía casi los mismos problemas, terminé haciendo por mi cuenta, tal vez esto ayude a alguien.

    https://github.com/mo22/jnipp

    Tiene un pequeño tiempo de ejecución de la huella (<30kb), administra las referencias, y apoya la generación de la clase Java interfaces.
    I. e. LocalRef> stringArray; y, a continuación, utilizando stringArray[1]->getBytes() o algo así.

  4. 2

    Volver a llamar a Java C++.

    Usted puede hacer lo que quiera, pero usted debe dejar de Java estar en control. Lo que quiero decir con esto es que usted cree hebras Java que llamar a código Nativo y a partir de ahí bloque, esperando su código nativo para darle algo que hacer. Crear, como muchas hebras Java como usted necesita conseguir suficiente trabajo /throuhput hecho.

    Para la aplicación de C++ se inicia, crea una JVM/JavaVM (como por el documentada, ejemplo existe en qtjambi codebase ver a continuación), este a su vez realice la costumbre JNI de inicialización y del Sistema.loadLibrary() y proporciona los Frascos con los «nativos» de la vinculación. Luego de inicializar un montón de hilos y llamar a algunos de JNI código (que creó) que puedan bloquear a la espera de su código de C++ para darles un poco de trabajo que hacer.

    Su código de C++ (presumabily de otro hilo), a continuación, configura y pasa toda la información necesaria para uno de los bloqueados y a la espera de Java Hilo de los trabajadores, luego se dio la orden de ejecutar, puede, a continuación, volver a puro código de Java para hacer el trabajo y volver con un resultado.

    Es posible configurar y crear y contener un JavaVM ejemplo de código C++. Esto puede ser alimentado a la fuerza de su propia CLASSPATH/Frascos para la instalación de la figura de medio ambiente necesita encapsulado dentro de su programa de C++.

    Esquema de que como estoy seguro de que ha encontrado ya en http://download.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

    Hay una clase de C++ => Java JNI generador en el QtJambi proyecto (que yo trabajo y ayudar a mantener). Esto es muy a la medida para el conjunto de herramientas Qt pero esencialmente se traduce en un montón de C++ archivos de encabezado en una colección de C++ .cpp/.h y archivos de *.archivo java para proporcionar la vinculación y la concha de contención del objeto de modo que el concurso de asignación de memoria de los esquemas de jugar bien juntos. Tal vez hay algo para ser tomado de esta.

    Esta es sin duda una prueba en cencept para lo que están pidiendo el generador sólo pasa a ser incluida en el qtjambi proyecto (pero podría hacerse independiente con algo de trabajo) y esta es la licencia LGPL (open-source). El conjunto de herramientas Qt no es una pequeña API sin embargo, puede generado 100s de clases para cubrir alto % de API (>85% y casi el 100% de Core/GUI partes).

    HTH

    • La parte de su respuesta sobre hilos no tiene sentido para mí. Ya puedo hacer algo mucho más sencillo que el uso puro de la JNI. Acabo de inicialización de la JVM, pedir que me carga una clase, llama al constructor en ella, llamar a sus métodos. Eso es todo allí está a él.
    • El QtJambi biblioteca es un proyecto para permitir el código de Java para utilizar la biblioteca Qt, es decir, Java llamada C++. Qué leer existentes de las clases de Java y producir los correspondientes C++ clases de contenedor, de modo que las clases de Java pueden ser fácilmente llamado de C++?
    • El hilo que se trata es de cómo configurar un proceso, de modo que C++ puede en cualquier momento de la llamada en Java de forma segura. Partes de la librería Qt son complejas, es una librería de C++, el cual también debe llamar de nuevo en Java. Usted puede registrar devolución de llamada/eventHandlers/subprocesos que se ejecutan en C++, pero de vez en cuando a invocar cosas en Java. Java Api puro de Java y también de C/C++. Pero la C/C++ no tiene Api para hacer las cosas en Java. No tiene sentido hacer un contenedor de C++ de Java cosas cuando Java ya tiene un API de C++ (es decir, la JNI).
    • Tal vez he redactado mi pregunta realmente mal o algo.
    • Esta es una idea muy interesante, parece que sólo requieren de algunos de refactorización en el c++ parte, pero el resto es principalmente basada en la pura JNI, que es muy estable. Sería agradable ver algunos ejemplos reales de este, tal vez alguien más lo ha probado?
  5. 1

    El artículo Java Consejo 17: la Integración de Java con C++ describe cómo hacerlo en detalle.

    • Bueno, supongo, pero que el artículo es de 1996 (se menciona que no hay ninguna manera de celebrar referencia mundial! Que fue añadido en la 1.2, una vez hace mucho tiempo). También el artículo se describe cómo escribir la JNI código de invocación a mano, que es lo que quiero evitar hacer con una herramienta de generación de código.
    • +1, cosas Buenas.
  6. 1

    También tuve muchas dificultades
    llegar JNI para trabajar en diferentes
    los sistemas operativos, para hacer frente con 32/64-bit arquitecturas y asegurarse de la correcta bibliotecas compartidas que se encuentran y se cargan.
    He encontrado CORBA (MICO y JacORB) difícil de usar también.

    No encontré la forma efectiva para llamar desde C/C++ a Java y mi preferido de soluciones en esta situación
    son para ejecutar mi código de Java como:

    1. un programa independiente
      que me puede ejecutar fácilmente de programas C/C++
      con java -cp myjar.jar org.foo.MyClass. Supongo que esto es demasiado simplista para su situación.

    2. Como un mini-servidor, la aceptación de las solicitudes de C/C++
      los programas en un socket TCP/IP y
      la devolución de resultados a través de esta toma demasiado.
      Esto requiere la escritura de redes y registrar las funciones de
      pero desacopla la C/C++ y Java procesos y claramente se puede
      identificar los problemas como en la de C++ lado o lado de Java.

    3. Como un Servlet Tomcat y hacer peticiones HTTP desde mi C/C++
      programa (otros contenedores de servlets también el trabajo también).
      Esto también requiere la escritura de redes y registrar funciones.
      Esto es más como SOA.

    • Gracias. Tengo JNI de trabajo en Windows y Linux sin problemas – parece básicamente idénticos. CORBA es la forma en que lo necesito. Cálculo de referencias de todas las llamadas fuera de proceso que parece un escrito a mano de la versión de las cosas que te dan de uso de SOA (o CORBA), y todos aquellos que tienen una gran sobrecarga adicional, y más complejidad.
    • Mientras tanto, la JNI sería la perfecta solución ligera, si sólo el conjuro para cada llamada al método (pasar el nombre del método y de la firma, la caché de ID, determinar la correcta sabor de Call[Static]MethodT, de verificación para las excepciones) podría ser limpiamente automatizado. Eso es todo lo que quiero.
    • Otro comercial del producto: javain.com/javain/oojni.jsp?cat=oojni&sub=whatIs
  7. 0

    Tal vez un poco demasiado grande martillo para este clavo, pero no es que lo CORBA fue construido para?

    • A partir de ese vínculo: «El C++, la cartografía es muy difícil; la asignación requiere que el programador para aprender complejo y confuso tipos de datos que son anteriores a la de C++ Biblioteca de plantillas Estándar» Suena muy bien! 🙂
  8. 0

    Responder a mi propia pregunta:

    http://java4cpp.kapott.org/

    No parece ser un proyecto activo. El autor recomienda que no se utilicen con JDK 1.5 o posterior.

    Parece tener un serio problema: se pasa alrededor de desnudo punteros a su envoltura de objetos:

    java::lang::Integer* i = new java::lang::Integer("10");
    
    delete i; //don't forget to do this!

    También causa un problema más sutil que en el fin de representar a la asignación de compatibilidad (por ejemplo, una clase como un subtipo de la interfaz que implementa) los contenedores tienen que heredar de uno a otro.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea