Jawin: Llamar metodos de una DLL con java

Jawin es una de las tantas librerias que se puede utilizar para poder trabajar los metodos de una DLL desde java. Lo mas comun era trabajar con JNI pero esto implicaba tener los fuentes de la DLL para poder realizar las modificaciones y volver a realizar la compilacion, algo tedioso en algunos casos.

Bueno una forma de utilizar esta libreria es creando una pequeña DLL en C con un metodo basico, por ejemplo el metodo “suma” que implica tener dos variables de entrada del tipo entero y retornar un valor entero. Para esto configuré NetBeans con el compilador gcc para poder desarrollar codigo en C/C++ siguiendo este manual, para luego crear un proyecto del tipo “C/C++ Dynamic Library”. Una vez creado este proyecto agrego un fuente al cual llamare “Suma.c” y dentro de este archivo creamos el metodo antes mencionado, quedando de la siguiente manera:

jawin_01

Como veran es algo simple y basico, ahora solo nos queda construir la DLL, para esto click derecho sobre el proyecto y elegimos “Build”, y listo ya tenemos generada nuestra DLL.

Ahora para poder utilizar el metodo de la DLL desde java, hacemos lo siguiente:

  • Primero agregamos la libreria jawin al proyecto (jawin.jar)
  • Luego segun nos indica la documentacion copiamos el archivo “jawin.dll” en el directorio “C:\windows\System32″.

Y listo ahora empezamos a escribir el codigo que llamaria al metodo, algo asi como esto:

jawin_02

Como podran ver el nombre de mi DLL es “LibSuma.dll”, tener en cuenta que el nombre de la dll lo da el nombre del proyecto(anteponiendose el sufijo “lib”, pero esto lo pueden variar en las propiedades del proyecto), y el metodo, en este caso “suma”; hago la invocacion dandole los parametros antes mencionados y en la variable “g” recepciono el resultado y listo. 

jawin_03

Cabe aclarar que yo puse solo el nombre de la libreria y no toda la ruta porque agregue la ruta de mi libreria a mi PATH. Otra forma seria colocar la libreria generada en “C:\Windows\System32″; o de lo contrario colocan toda la ruta de la libreria incluida el nombre.

Como veran para este caso es algo sencilo de trabajar y no tan tedioso, yo ahora estoy en un proyecto algo mas grande trabajando con esta libreria y la verdad me esta dando resultados.

23 comments so far

  1. DANIEL on

    Gracias por la info, pero porfavor, me podrias aclarar mas al detalle la ultima parte de donde ubicas la libreria DLL y como haci lo ubicas en el classpath. medio q no la capto. gracias.

    • nachxs on

      Hola Daniel, claro, mira cuando tu creas una DLL cualquiera, si quieres ejecutar o llamarla desde cualquier aplicacion tienes 3 opciones:
      - La primera es colocar toda la ruta donde esta ubicada tu dll incluido el nombre en la invocacion en tu aplicacion
      - La segunda forma es que la coloques en el PATH (Click derecho MI PC –>Propiedades–>Opciones Avanzadas–>Variables Entorno–>Variables de Sistema) la ruta del directorio en donde tienes tu DLL (sin el nombre de la DLL) al final de todo el contenido, de esta forma cualquier aplicacion que haga la invocacion sabra donde encontrarla.
      - Y la tercera es colocar tu libreria dentro del directorio C:\Windows\system32, dado que esta carpeta ya esta en la path por defecto.

      en la 2 ultimas forma solo colocarias el nombre de la DLL en tu aplicacion de la manera como yo la hago. Espero me haya dejado entender.

      Saludos.

  2. DANIEL on

    Gracias por la rapidez de respuesta y si quedo claro.

    Pero me sale este problemilla, explico:
    cree un dll en C con vb .net 2008 me genero: “Suma.dll” y lo ubique en C:\Windows\system32

    En la clase java puse todo esto:
    public static void main(String[] args) throws COMException {

    FuncPtr metodo = new FuncPtr(”LibSuma.dll”, “suma”);
    Integer g = metodo.invoke_I(10, 12, ReturnFlags.CHECK_HRESULT);
    System.out.println(”Resultado = ” + g);

    }

    Prove tmb quitandole el sufijo “Lib” para llamar al dll pero no levanta, me sale este mensaje por consola:

    Exception in thread “main” org.jawin.COMException: 8007007e: No se puede encontrar el módulo especificado.

    at org.jawin.Bootstrap.loadLibrary(Native Method)
    at org.jawin.FuncPtr.(FuncPtr.java:79)
    at javaapplication.Main.main(Main.java:23)
    Java Result: 1
    BUILD SUCCESSFUL (total time: 2 seconds)

    y me hace referencia a la linea donde declaro al dll y su metodo:

    >>>FuncPtr metodo = new FuncPtr(”LibSuma.dll”, “suma”);

    No se si es por la version del jar o no se q mas pensar q puede ser.
    te comento q me baje el jawin q viene en esta carpeta: jawin-2.0-alpha1
    no se enque estoy errando, haber si me puedes enviar el ejemplo a mi correo giancuse@hotmail.com.

    Saludos.

    • nachxs on

      Hola Daniel, mira el problema esta en que tu no colocaste la libreria propia de Jawin (jawin.dll) en el C:\Windows\system32, si te dfijas en el paquete jawin que descargaste alli tienes un jar y una dll. La dll deberias colocarlo en C:\Windows\system32.
      Con eso ya no te deberia salir este error

      Saludos.

  3. DANIEL on

    Bueno nachxs, te agradesco el tiempo q le das a responder a mi dudas. Se segui tu ejemplo puse el jawin.dll en C:\Windows\system32 pero sigue con el mismo mensaje.

    • nachxs on

      No te preocupes Daniel, dime una cosa que version de Windows usas??, porque a mi me sale ese error cuando no tengo la dll en el system32, o de lo contrario seteas en tu PATH (variables de entorno) el directorio del jawin (tu_directorio/jawin/bin).

      Me comentas.

  4. DANIEL on

    agregue la ruta “C:\jawin-2.0-alpha1\bin\” donde esta el jawin.dll pero sigue igual. Tengo el XP Professional SP3.

    Te comento que hice lo mismo con el eclipse y dan el mismo mensaje.

    mi dll se llama Suma.dll al momento de llamarlo en la clase java lo declaro como LibSuma.dll es asi como lo entendi, es correcto ese procedimiento.

    estoy penssando en probarlo en otro cpu.

    • nachxs on

      A ver vayamos por partes:

      1. A ver primero fijate como se llama la libreria que generaste, si se llama Suma.dll tienes que ponerle el mismo nombre cuando lo invocas desde java.
      2. Otra cosa es que tienes que agregar la libreria jawin.jar a tu proyecto (imagino que eso lo tenias, por eso no te pregunte antes).
      3. y al final agregas la libreria jawin.dll a “c:\windows\system32″ o seteas el path como te indique.

      Con esto deberia funcionarte, porque segun la documentacion eso es lo unico que se hace. Revisa eso y me comentas

      Saludos.

  5. DANIEL on

    Amigo nachxs hice todo como me explicaste inportando el jawin.jar todo eso. Pero por razones desconocidas no levanta y me sale el mismo error.

    • nachxs on

      MMMM, Daniel dentro de la dll tienes un metodo cierto?? como se llama el metodo?? se llama “suma”??, te lo pregunto porque quizas tu metodo tenga otro nombre.
      Ahora por otro motivo no sabria decirte exactamente a que deba el error, todo lo que te indique es lo que hice y no tube problemas.

  6. Ignacito on

    Hola, para el paso de parametros que sean de entrada y salida, como se realiza?

    Es decir, yo tengo una funcion con esta cabecera

    int LeeIDFabricante (char * CadFabricante);

    y no se como hacerlo exactamente, yo había hecho:
    int Resultado = metodo1.invoke_I(CadenaFabricante, ReturnFlags.CHECK_HRESULTS);
    pero no me modifica el valor del String de entrada, como puedo realizarlo?

    • nachxs on

      Hola Ignacito, no probe un metodo con puntero pero publica el metodo para poder plasmarlo y asi ver cual podrias ser el error.

      Saludos.

  7. Carlos Torres on

    Hola nachxs, mucho gusto, yo tambien tengo el mismo problema que Daniel.

    • nachxs on

      Hola Carlos, mira estoy probando la posibilidad de que el error se de por el Service Pack 3, yo cuando trabajaba con el Service Pack 2 no he tenido este problema, pero desde que actualize el 3 ahora me esta dando el mismo problema, vere si es por eso o buscare otra alternativa.

      Saludos.

  8. Carlos Torres on

    Hola nachxs, gracias por la pronta respuesta, el problema mio es que estoy intentando leer un dll para manejo de lectores de tecnologia rfid. Lo que pasa es que ahorita no estoy en mi casa para darte mas informacion, o un correo tuyo para enviarte el dll. De verdad te agradezco la ayuda que me puedas dar. De verdad muchas gracias.

    • nachxs on

      Enviamelo a nachxs[arroba]gmail.com

      Saludos.

  9. Ignacito on

    Como el parámetro que le paso es un punto a un char en realidad, lo que he hecho es pasarle como entrada un array de bytes, a ver si así iba bien, pero no he conseguido que vaya… no me modifica el valor de entrada. El método en sí esta en asm, no se si servirá mucho

    metodo1 = new FuncPtr(”P2_Libreria.dll”, “LeeIDFabricante”);
    byte CadenaFabricante [] = new byte [13];
    int Resultado;
    Resultado = metodo1.invoke_I(CadenaFabricante, ReturnFlags.CHECK_HRESULT);

    La función en sí es:

    __declspec (dllexport) int LeeIDFabricante (char * CadResultado)
    {
    __asm
    {
    mov eax, 0
    cpuid
    mov eax, CadResultado
    mov [eax], ebx
    mov [eax + 4], edx
    mov [eax + 8], ecx
    mov [eax + 12], 0
    mov eax, 0
    cpuid
    }

    }

    Resultado si me devuelve lo que me tiene que devolver, pero CadenaFabricante no

  10. Ignacito on

    La salida debe ser del tipo “GENUINTEL” , o algo del estilo

  11. Jou on

    invoke_I es para devolver enteros, invoke_S es para devolver cadenas, pero, ¿como funciona? Puedes poner un ejemplo? Gracias

    • nachxs on

      Funciona igual, la unica diferencia es que no tendras un entero como resultado, si no una variable del tipo byte[].
      byte[] out = metodo.invoke_S(20,30,ReturnFlags.CHECK_HRESULT);
      System.out.println(”result: ” + out.toString());

  12. Luis Alejandro on

    Hola nachxs, muy interesante este tema, esta genial,
    solo una pregunta…
    También funciona con dll’s echas en Visual Studio 2008 C++?
    ya ves que para que los programas corran se necesita el .NET Framework, entonces no se si sea lo mismo hacer un dll en cygwin y hacer un dll en c++ .net,
    muchas gracias por tu respuesta.

    Saludos…

  13. Manuel on

    Funciona tambien con una dll propia de windows? esa dll tu la hiciste en c, como podria llamar yo una dll propia de windows desde java?
    Habia leido que haciendo un puente con C++ es decir que C++ llamara la dll de windows y yo llamara la dll de C++? tienes alguna sugerencia, pues no se como invocar metodos de dll desde c++ y poder usar un puente.

    Saludos a todos.

    • nachxs on

      Hola Manuel, la dll lo que cree con C y lo compile con gcc sobre windows, configurando Netbeans. Ahora para poder llamar a una dll propia de windows, jawin porporciona en la documentacion un ejemplo de una forma de hacerlo.

      Ahora, otra alternativa muy buena tambien es Jacob que es una libreria con la que puedes hacer lo mismo.

      Saludos.


Replica