Pregunta

Estoy escribiendo un código JNI en C ++ para que se llame desde un applet en Windows XP. He podido ejecutar con éxito el applet y tener la biblioteca JNI cargada y llamada, incluso llegando a llamar a funciones en otras DLL. Obtuve esto funcionando configurando la variable de entorno del sistema PATH para incluir el directorio en el que están todas mis DLL.

Entonces, el problema es que agrego otra llamada que usa una nueva DLL externa y, de repente, al cargar la biblioteca, se lanza un UnsatisfiedLinkError. El mensaje es: "No se pudo encontrar el procedimiento especificado". Esto no parece ser un problema con una DLL dependiente que falta, porque puedo eliminar una DLL dependiente y obtener un mensaje diferente sobre la falta de DLL dependiente. Por lo que he podido encontrar en línea, parece que este mensaje significa que falta una implementación nativa de la función Java en la DLL, pero es extraño que funcione bien sin este bit adicional de código.

¿Alguien sabe qué podría estar causando esto? ¿Qué tipo de cosas pueden dar mensajes de 'No se pudo encontrar el procedimiento especificado' para un UnsatisifedLinkError?

¿Fue útil?

Solución

Resolví el problema. Esto fue un doozy. El mensaje "No se pudo encontrar el procedimiento especificado" for UnsatisfiedLinkError indica que no se pudo encontrar una función en la raíz dll o en una dll dependiente . La causa más probable de esto en una situación JNI es que la función JNI nativa no se exporta correctamente. Pero esto aparentemente puede suceder si se carga una DLL dependiente y esa DLL no tiene una función requerida por su padre.

A modo de ejemplo, tenemos una biblioteca llamada input.dll. El orden de búsqueda de DLL es buscar siempre en el directorio de la aplicación primero y en último lugar los directorios PATH. En el pasado, siempre ejecutamos ejecutables desde el mismo directorio que input.dll. Sin embargo, hay otro input.dll en el directorio del sistema de Windows (que está en el medio del orden de búsqueda de DLL). Entonces, cuando ejecuto esto desde un applet de Java, si incluyo el código descrito anteriormente en el applet, que causa que se cargue input.dll, carga input.dll desde el directorio del sistema. Debido a que nuestro código espera ciertas funciones en input.dll que no están allí (porque es una DLL diferente), la carga falla con un mensaje de error sobre los procedimientos faltantes. No porque las funciones JNI se exporten incorrectamente, sino porque se cargó la DLL dependiente incorrecta y no tenía las funciones esperadas.

Otros consejos

Existe la posibilidad de que la DLL se haya creado utilizando C ++ (en lugar de C). a menos que haya tenido cuidado de hacer un procedimiento externo, esta es una posible razón.

Intente exportar todas las funciones de la DLL. Si la lista incluye su función, entonces está bien.

Por lo general, al vincular a otras bibliotecas, debe vincular al archivo .lib relevante. Parece que no estás haciendo referencia a todos los archivos lib que necesitas. Compruebe lo que no está enlazando y asegúrese de agregar su lib a la lista para el enlazador.

¿Creó la nueva DLL externa utilizando el procedimiento JNI estándar? Es decir, ¿usando javah y demás? Si es así, entonces no estoy seguro de lo que está mal.

Si no, entonces el procedimiento al que está intentando llamar no se ha exportado (como lo menciona anjanb). Conozco dos formas de exportar funciones: una lista de exportación separada y marcar funciones específicas con __declspec (dllexport).

No se puede acceder a la variable en C ++ DLL desde una aplicación C tiene un poco más de información sobre el tema de las DLL.

Compile su código c ++ en modo de depuración. Luego inserte el DebugBreak (); declaración donde le gustaría comenzar a depurar. Ejecute el código de Java. Cuando se encuentra la declaración DebugBreak (), aparecerá una ventana emergente con un botón de depuración. Haz click en eso. Dev Studio se abrirá con su programa en código máquina. Pase dos veces con el depurador y debería poder pasar su código fuente.

Si ha realizado todos los problemas de programación en los manuales y ejemplos de JNI, pero aún está recibiendo el mismo error de procedimiento faltante, el problema puede estar probablemente en su variable de ruta. Siga los pasos a continuación y vuelva a ejecutar:

  1. Asegúrese de establecer la variable JAVA_HOME en su carpeta JDK (no JRE porque JRE no contiene el encabezado jni) Ejemplo: En el panel de configuración de variables de entorno, defina var: JAVA_HOME val: C: \ Program Files \ Java \ jdk1.7.0_11
  2. agregue % JAVA_HOME% \ bin a su variable de ruta

Después de realizar esos pasos, su aplicación puede encontrar el nombre del procedimiento jni y los enlaces a JNI.dll de la manera correcta. Entonces, espero que no vuelva a aparecer este error de procedimiento faltante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top