Acessar um .dll usando JNI

35 respostas
F

Fala pessoal,
Li bastante coisa aqui no fórum e na internet, mas não to entendendo aonde está dando errado.

Eu preciso criar um programa em Java que carregue uma .dll de uma câmera digital (criada em C++), e use uma função dela, chamada InicializaSDK, e estou usando JNI pra isso.

Tentei criar uma wrapper para carregar, mas tá dando um erro... aí vai o que eu tentei fazer:

1- Primeiro criei o...
...Inicia.java:

public class Inicia{
	public native void InicializaSDK();
	
	public static void main (String[] args){
		Inicia c = new Inicia();
		c.InicializaSDK();
	}
	
	static{
		System.load("C://j2sdk1.4.2_12//bin//CDSDK.dll");
	}
}

2- Depois, compilei com o javac e usei o javah pra criar o...
...Inicia.h:

#include <jni.h>
/* Header for class Inicia */

#ifndef _Included_Inicia
#define _Included_Inicia
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Inicia
 * Method:    InicializaSDK
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

3- Então, escrevi o arquivo...
...Inicia.cpp:

#include <jni.h>
#include <stdio.h>
#include "Inicia.h"

JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *env, jobject obj){
	return InicializaSDK();
}

E daí quando tento usar o "gcc -shared Inicia.cpp -o CDSDK.dll" ele dá erro.
Alguém sabe onde eu estou errando, ou o quê eu devo fazer?
Valeu, abração!

35 Respostas

T

Eu não queria ser chato, mas você tem como usar o Microsoft Visual Studio 2003 ou 2005? É que não sei se é possível escrever uma DLL JNI com o mingw (gcc para Windows).

F

Teria sim! Ou com o DevC++ também.

T

Eu vou postar aqui uma DLL JNI que fiz faz algum tempo com o MS VC++ 6.0. O 2003 ou 2005 são parecidos, você só precisa abrir uma linha de comando (No caso do Visual Studio 2005, Start -> Programs -> Microsoft Visual Studio 2005 -> Tools -> Visual Studio Tools -> Visual Studio 2005 Command Prompt, e ele abrirá uma linha de comando em que você pode usar o “cl” (compilador de linha de comando), “nmake”, etc.

TESTEJNI.CPP

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "TesteJNI.h"

/**
 * @param env O JNI Environment
 * @param isto "this" do Java
 * @param mo Um objeto MeuObjeto.
 * @return  para enfeitar, vamos retornar o comprimento de mo.cadeia, em caracteres.
 */
JNIEXPORT jint JNICALL Java_TesteJNI_alteraObjeto
  (JNIEnv *env, jobject isto, jobject mo) {
    // Queremos simplesmente fazer 
    // mo.numero = mo.numero + 10
    // mo.cadeia = mo.cadeia + "!!!!"
    
    //-- Puxar a classe MeuObjeto
    jclass jcMeuObjeto = env->GetObjectClass (mo);
    //-- Puxar os campos:
    jfieldID jfiNumero = env->GetFieldID(jcMeuObjeto, "numero", "I");
    jfieldID jfiCadeia = env->GetFieldID(jcMeuObjeto, "cadeia", "Ljava/lang/String;");
    //-- Puxar os valores e efetuar as atribuições correspondentes:
    int numeroAntigo = env->GetIntField (mo, jfiNumero);
    int numeroNovo = numeroAntigo + 10;
    env->SetIntField (mo, jfiNumero, numeroNovo);
    
    jstring jsCadeia = (jstring) env->GetObjectField (mo, jfiCadeia);
    const char *str = env->GetStringUTFChars (jsCadeia, NULL);
    const char *bangs = "!!!!";
    // Vamos fazer a concatenação em C - você ainda se lembra como fazer isso?
    char *result;
    if (str == NULL) {
        //-- Vamos imitar o comportamento do Java, e usar a string "null"
        result = (char*) calloc (1, strlen ("null") + strlen (bangs) + 1); 
        strcpy (result, "null");
        strcat (result, bangs);
    } else {
        result = (char*) calloc (1, strlen (str) + strlen (bangs) + 1);
        strcpy (result, str);
        strcat (result, bangs);
        env->ReleaseStringUTFChars (jsCadeia, str);
    }
    //-- Agora efetuando a atribuição
    jsCadeia = env->NewStringUTF (result);
    free (result);
    env->SetObjectField (mo, jfiCadeia, jsCadeia);
    
    
    //-- Retornando 0  para enfeitar
    int lenCadeia = 0;
    return lenCadeia;
}

TESTEJNI.H

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class TesteJNI */

#ifndef _Included_TesteJNI
#define _Included_TesteJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     TesteJNI
 * Method:    alteraObjeto
 * Signature: (LMeuObjeto;)I
 */
JNIEXPORT jint JNICALL Java_TesteJNI_alteraObjeto
  (JNIEnv *, jobject, jobject);

#ifdef __cplusplus
}
#endif
#endif
class MeuObjeto {
    public int numero;
    public String cadeia;
    public String toString () {
        return "numero = " + numero + ", cadeia = " + cadeia;
    }
}

class TesteJNI {
    public native int alteraObjeto (MeuObjeto obj);
    
    /**
     * Compilar com (se for usar o Microsoft Visual C++ 6.0):
     * javac TesteJNI.java
     * javah TesteJNI
     * cl -LD -MT -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 TesteJNI.cpp
     *    jvm.lib -link /libpath:%JAVA_HOME%\lib
     */
    public static void main(String[] args) {
        System.loadLibrary ("testejni");
        MeuObjeto mo = new MeuObjeto();
        TesteJNI tjni = new TesteJNI();
        mo.numero = 10;
        mo.cadeia = "Alo, mundo";
        System.out.println ("Antes: " + mo);
        tjni.alteraObjeto (mo);
        System.out.println ("Depois: " + mo);
    }
}

Use as opções de linha de comando especificadas no comentário do programa Java.

F

Thingol,
Valeu pela ajuda velho!
Mas então, a minha idéia era apenas chamar aquela função (void: void) já existente na CDSDK.dll (essa, uma .dll já existente também, instalada com o sw da câmera digital, provavelmente não foi criada usando os argumentos de JNI), e não preciso fazer nenhuma operação com essa função (pelo menos por enquanto não), só chamar sua execução.

E isso eu não captei ainda… e isso que me falaram de criar a wrapper.
Any idea?

F

Nada ainda aqui =/

T

Pois é, eu postei algo que eu já tinha, só para lhe mostrar as opções de compilação.

F

Sim sim, essa parte de compilar eu “sei”.
O que me falta é isso de acessar uma .dll já existente pra usar uma função dela.
Sabe alguma maneira Thingol?

T

Você conhece suficientemente C? Basicamente você tem de chamar a tal função da DLL a partir da DLL JNI que você vai criar.

Se a tal DLL veio com um arquivo .H e um arquivo .LIB é fácil chamar o método InicializaSDK a partir de seu programa C.
Senão, você terá de chamar as APIs do Windows “LoadLibrary”, “GetProcAddress”, e “FreeLibrary”.

F

Conheço o suficiente pra fazer isso sim acho.
E a DLL veio sim com .H e o .LIB, mas eu nunca manipulei .LIB, não sei como fazê-lo, e não sei como (ou se) devo “linkar” o arquivo DLL JNI com o DLL que contém a função.

O que eu consegui imaginar foi o que eu postei aqui mesmo, mas sei que meu arquivo .cpp está errado, e acho que é exatamente por não estar “linkando” com o DLL ou com o LIB que você disse.

To meio perdido nessa parte.

T

Então tá.

  1. Crie uma classe Java com apenas um método estático (digamos que seja “public native void inicializaSdk();”), e talvez um método estático para carregar a DLL (System.loadLibrary ou System.load), e a compile.
  2. Use o javap para criar o arquivo .h.
  3. Crie um arquivo em C ou C++ que inclua o .h criado no passo 1, e que implemente o tal método que está definido no .h. Esse arquivo em C ou C++ deve incluir também o .h que define o tal método InicializeSDK do seu toolkit.
  4. Compile esse arquivo em C ou C++ e o linke com
    o tal .LIB que você recebeu. Isso irá gerar a tal DLL JNI.
F

Parte 1) Classe .java criada

public class Inicia{
	public native void InicializaSDK();
	
	public static void main (String[] args){
		Inicia c = new Inicia();
		c.InicializaSDK();
	}
	
	static{
		System.load("C://j2sdk1.4.2_12//bin//CDSDK.dll");
	}
}

Parte 2) Arquivo .h criado com o javah

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Inicia */

#ifndef _Included_Inicia
#define _Included_Inicia
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Inicia
 * Method:    InicializaSDK
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Parte 3) Arquivo .cpp (essa parte eu não tenho certeza se está certa; eu copiei a implementação da função InicializaSDK() que estava no arquivo .cpp (o original, onde está a implementação dessa função) e coloquei em formato de JNI, mas não tenho certeza se é essa mesma a idéia. Acho que a intenção é acessar a InicializaSDK() direto da .dll ou da .lib que eu possuo, e não copiar sua implementação pra um novo .cpp, aí que eu estou me perdendo)

#include <jni.h>
#include <stdio.h>
#include <windows.h>
#include "cdAPI.h"  //header que define "cdError", "cdVersionInfo", "cdHEnum", "CDStartSDK()", "CDGetSDKVersion()", "CDFinishSDK()"
#include "Inicia.h"  //header criado usando o javah

JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *env, jobject obj){

     //daqui pra baixo está a copia da implementação da função InicializaSDK(), encontrada no .cpp original.
     static HWND   Form1;
     cdError err;
     cdVersionInfo Ver; 
     cdHEnum hEnumD;
      
     memset(&Ver, 0, sizeof(cdVersionInfo));
     
     char temp[256];
     
     
     Ver.Size = sizeof(cdVersionInfo);
     Ver.MajorVersion = 7;
     Ver.MinorVersion = 3;

     err = CDStartSDK(&Ver, 0); 
     
     err=CDGetSDKVersion(&Ver);
	 sprintf(temp,"size:%d major:%d minor:%d release:%d chVersion:%s",Ver.Size,Ver.MajorVersion,Ver.MinorVersion,Ver.ReleaseVersion,Ver.chVersion);


     SetWindowText(Form1,temp);    
    
     if(err != cdOK) 
       CDFinishSDK();
}
Parte 4) Compilei o projeto e linkei com a .LIB e a .A já existentes, assim criando a .dll, mas quando eu rodo (usando javac):
Exception in thread "main" java.lang.UnsatisfiedLinkError: InicializaSDK
             at Inicia.InicializaSDK(Native Method)
             at Inicia.main(Inicia.java:6)

Eu estou errando no passo 3 mesmo? Eu tenho que fazer a chamada diretamente da minha .LIB ou da .DLL? Ou estou fazendo corretamente?
Abraço!

F

Opa!
Meu orientador disse que a idéia é só chamar a função InicializaSDK() mesmo, e não declarar tudo de novo.

Dessa forma o passo 3 ficaria:

#include <stdio.h>
#include <jni.h>
#include "Inicia.h"


JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *env, jclass cls){
          InicializaSDK();
          return;
  }

Só que assim ele não compila, diz que 'InicializaSDK' undeclared (first use this function) =/
E ah Thingol, eu tenho a .DLL, a .LIB e a .A; a .H que eu tenho define alguns métodos do corpo da função InicializaSDK() (CDStartSDK() e CDFinishSDK() como visto no post anterior), mas não nenhum que defina a própria função que eu desejo.

Abraço!

T

Hum…
Você está mostrando um arquivo .A. O que ele está fazendo aí?
Qual é o compilador que você está usando? Nunca vi ninguém dizendo que teve sucesso ao usar o mingw (gcc para Windows) para escrever DLLs JNI, por exemplo.

F

O .A eu coloquei junto como parâmetro apenas pq estava na mesma pasta que o .LIB, não sei se é correto fazer isso.
Estou criando a .DLL JNI com o DevC++ mesmo.

Pra linkar a .LIB e a .A eu cliquei em “Opções de Projeto”, depois na aba “Parâmetros”, e na janela “Linker” eu adicionei ambos e dei OK, só isso ehehehhe

T

Não tenho a menor idéia como se usa o DevC++. Por acaso isso é uma IDE que usa o mingw?

F

Na verdade eu nunca usei o mingw.
O DevC++, quando você escolhe “Novo Projeto” ele te pergunta o que você quer criar (um executável de Windows, uma .A, uma .DLL, etc), e nessa hora eu escolho por criar uma .DLL, adiciono um arquivo .H (criado usando o javah) e o .C ou .CPP (que é onde eu devo chamar a função, e logo, onde eu to com problema) e compilo o projeto, assim criando uma .DLL.

Eu estava fazendo os exemplos do tutorial da Sun e funcionou pra todos a .DLL criada, mas nenhum desses exemplos chamava uma função de uma .DLL já existente.

L

Tente colocar a DLL no path. Sabe aquele erro básico que a gente tem no inicio de não conseguir chamar o ‘javac’ por não está no PATH? É mais ou menos o que acontece aqui. O carregamento da DLL é problema do SO, então ele precisa saber onde procurar as DLLs.

:slight_smile:

L

Cuidado ao usar MinGw e Cygwin. Eles servem básicamente, não somente pra isso, para compilar e executar códigos desenvolvidos para linux. Então, quando vc gera uma lib através destes dois, você estará gerando uma no padrão linux, tem como faze-la rodar em windows, mas é muita complicação.

T

Aqui vou tirar minha camiseta preta da Microsoft da gaveta e pedir para você baixar o MS Visual Studio (C++) 2005 Express. Realmente não consigo lhe ajudar com DLLs JNI geradas pelo DevC++. A Sun gera o JDK com o compilador da Microsoft (para o JDK 6 eles usam o Visual Studio .NET 2003, se não me engano).

F

Eu nem to usando nenhum desses aí não, só o DevC++, e todas as .DLL que eu criei até agora usando ele funcionaram.
Eu tenho o Visual aqui, mas ele não cria bibliotecas dinâmicas, só estáticas, e nem vejo porque usá-lo, já que com o DevC++ tava dando tudo certo até agora.

Teoricamente, o que eu estou fazendo no arquivo .cpp está certo? Seria só fazer essa chamada mesmo?

F

Se alguém quiser dar uma olhada, aí estão todos os arquivos que eu tenho:

cam.cpp - Arquivo original de onde foi feita a .dll, aí está a implementação da função InicializaSDK()

CDSDK.def, CDSDK.lib e libCDSDK.a - Vieram numa mesma pasta, chamada “lib”, a .LIB é a biblioteca que eu teria que chamar.

CDSDK.dll - Encontrei na pasta da camera digital também, imagino que seja a mesma coisa que a .lib

Inicia.h, Inicia.java e IniciaImp.cpp - Tudo que eu consegui fazer até agora. O arquivo .java chamando o método nativo, o arquivo .H criado pelo javah e o arquivo .CPP que deve chamar a função.

F

Possíveis novidades! Descobri algumas coisas, meu código atualmente é o seguinte:

Inicia.java
public class Inicia{
	public native void InicializaSDK();
	
	public static void main (String[] args){
		Inicia c = new Inicia();
		c.InicializaSDK();
	}
	
	static{
		System.load("C://j2sdk1.4.2_12//bin//Inicia.dll");
	}
}
Inicia.h (criado usando o javah):
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Inicia */

#ifndef _Included_Inicia
#define _Included_Inicia
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Inicia
 * Method:    InicializaSDK
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
....e, quem estava/está dando problema. IniciaImp.cpp:
#include <stdio.h>
#include <windows.h>
#include <jni.h>
#include "Inicia.h"


JNIEXPORT void JNICALL Java_Inicia_InicializaSDK
  (JNIEnv *env, jobject obj){
          typedef void (*inisdk)(); 
          HINSTANCE hdll;
          inisdk Inicio;  
  
          hdll = LoadLibrary("CDSDK.dll");
          
          Inicio = (inisdk)GetProcAddress(hdll, "InicializaSDK");
          Inicio();
}

Agora, quando eu compilo o projeto da DLL JNI (que contém o Inicia.h e o IniciaImp.cpp), ele avisa que "nenhuma aplicação local foi fornecida", seja lá o que isso queira dizer, mas cria a Inicia.dll certinho.
E quando eu vou rodar o arquivo Inicia.java, ele dá um erro bizarro, falando que foi descoberto pela HotSpot Virtual Machine, chamado EXCEPTION_ACESS_VIOLATION.

Acho que to no caminho, mas ainda meio perdido, alguém?

L

Primeiro, ao invés de usar System.load() use System.loadLibrary() (NO CÓDIGO JAVA!). Para esta ultima forma funcionar a dll tem que está no PATH do SO.

Segundo, agora vc está programando em C!! Meu tutor em C me disse o seguinte: “Essa é uma linguagem de homem, vc precisa saber exatamente o que vc está fazendo, pq ela permite fazer tudo inclisive m****!”. Hehe

Esse erro Acess Violation é um erro comum no C/C++, é quando vc “pisa” na memoria.

Adicionei algumas verificações ao seu codigo! Tente coloca-las no seu projeto e diz se ainda rola o Acess Violation! Pq o erro pode está na implementação do metodo InicializaSDK.

#include <stdio.h>   
#include <windows.h>   
#include <jni.h>   
#include "Inicia.h"   
  
  
JNIEXPORT void JNICALL Java_Inicia_InicializaSDK   
  (JNIEnv *env, jobject obj){   
          typedef void (*inisdk)();   //Aqui vc está declarando um ponteiro de função
          HINSTANCE hdll;   //Handler
          inisdk Inicio;     
     
          //Aqui vc está carregando a DLL em memoria
          hdll = LoadLibrary("CDSDK.dll");   
          
          //Verificamos se o handler foi carregado com sucesso.
          if( !hdll ){
              printf( "Nao conseguir carregar a lib em memoria!\r\n" );
              exit(-1);
          }
             
          //Atribuindo o endereço de memoria do metodo a nossa variavel Inicio
          Inicio = (inisdk)GetProcAddress(hdll, "InicializaSDK");   
          if( !Inicio ){
              printf( "Nao conseguir localizar o metodo dentro da lib!\r\n" );
              exit(-2);
          }else
              Inicio();   
}

No C/C++ as verificações ficam por sua conta!
:slight_smile:
Luca

F

Nossa Luca, valeu mesmo cara! Funcionou! =)
Quer dizer, ele entrou no erro de “Nao conseguiu localizar o metodo dentro da lib”, (não entendi pq, enfim)mas já é uma bela evolução!
Vou tentar ver o que está errado. Valeu de novo!
Abraço!

T

Isso pode ocorrer, entre outras coisas, porque é necessário usar um arquivo .DEF. Veja como é que se criam arquivos .DEF no MSDN.

F

thingol:

Nao conseguiu localizar o metodo dentro da lib

Isso pode ocorrer, entre outras coisas, porque é necessário usar um arquivo .DEF. Veja como é que se criam arquivos .DEF no MSDN.

Tipo, eu tenho a CDSDK.DLL e a CDSDK.LIB, mas a .LIB, quando eu tento carregá-la, ele fala que essa não é uma imagem válida para Windows, por isso eu to carregando a .DLL mesmo.
A biblioteca CDSDK.LIB já veio com um .DEF, mas onde devo colocá-lo? Ou devo criar um .DEF para a CDSDK.DLL?

L

Fabricio, esse metodo realmente existe? Se ele existe qual a assinatura dele? A assinatura consiste no nome, retorno e parametros do metodo.

Se assim não rolar a gente pode tentar uma outra alternativa que é ao invés do LoadLibrary, usaremos a diretiva de pré-compilação #pragma.

F

Luca, então, meu orientador disse que ele existe no CSDSK.lib, e eu imaginei que existisse também np CDSDK.dll.
Tentei carregar a .LIB e, como disse, ele fala que essa não é uma imagem válida para Windows.

Eu tenho o arquivo .cpp de onde foi criado o .LIB (e imaginei que a .DLL também), e lá está definida a função InicializaSDK() que não recebe parâmetros e nao retorna nada.

Sabe algum modo de carregar a .LIB?

L

Cara, estou sem compilador C/C++ aqui.
Inicialmente uns links de exemplo:

http://msdn.microsoft.com/en-us/library/7f0aews7(VS.80).aspx
http://doc.ddart.net/msdn/header/include/objbase.h.html

Coloque no seu header a seguinte diretiva:

#pragma comment(lib, "CDSDK.lib")

Lembre-se de colocar o .h que contem as prototipos da função que foi implementada na lib!

Na configuração de compilação adicione a lib.
Não me lembro como é no DevC++, mas na linha de chamando o compilador na mãe seria o parametro -l.

Se mesmo assim não der, tem como vc compartilhar o projeto? Assim eu posso testar por minha conta e assim até arriscar uma tentativa e erro.

L

Cara, na .lib e na .dll não existe nenhum metodo chamando InicializaSDK() , o mais próximo que encontrei foi CDStartSDK, julgando pela assinatura deve retornar um int. Nos arquivo publicador eu não vi um .h que contivesse a assinatura dos metodos, acho que está faltando.

F

Fala Luca!
Cara, não sei nem como agradecer vc e o Thingol!
Realmente não tinha nenhum método InicializaSDK(), e consegui carregar o CDStartSDK()! =) Vou avisar meu orientador sobre isso!
Como você conseguiu ver isso na .DLL?

Bom, obrigado por tuuuuuuuudo mesmo velho! =) Qualuqer coisa eu volto aqui!
Abração!

E

fabriciocarraro

Boa tarde, voce sabe me dizer porque quando eu rodo o javah dá este erro?
O javac funciona certinho, mas esse bendito javah ta pho…

C:\Documents and Settings\hz6vhd\ProgramasNetBeans\JNI\src\jni>javah -jni OlaMundo error: cannot access OlaMundo class file for OlaMundo not found javadoc: error - Class OlaMundo not found. Error: No classes were specified on the command line. Try -help.
Muito obrigado.

E

Salve galera....

Tive muitas dificuldades em executar javah, entender o classpath, etc. Tenho tido novos resultados agora, to seguindo um tutorial e muitas, muitas dicas aqui do GUJ. Mas vamos lá....agora eu to tendo um probleminha com .dll. To fazendo um exemplo simples com o famoso "ola mundo".

crie a parte do java
package jni;

class OlaMundo { //declaração da classe
    public native void diga();//declaração do metodo nativo "diga"
    public native void diga2();//declaração do metodo "diga2"
    
    static {
        System.loadLibrary("OlaMundo"); //carrega a biblioteca "OlaMundo"
    }
    public static void main(String[] args) {//metodo main
        OlaMundo ola = new OlaMundo();//uma instancia da classe OlaMundo
        ola.diga();//ola chamando o metodo nativo "diga"
        ola.diga2();//ola chamando o metodo nativo "diga2"
    }
}

compilei com javac.

gerei o .h com javah

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jni_OlaMundo */

#ifndef _Included_jni_OlaMundo
#define _Included_jni_OlaMundo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jni_OlaMundo
 * Method:    diga
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jni_OlaMundo_diga
  (JNIEnv *, jobject);

/*
 * Class:     jni_OlaMundo
 * Method:    diga2
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jni_OlaMundo_diga2
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

criei o metodo nativo no Dev-C++ criando a dll OlaMundo.dll

#include <jni.h>
#include "jni_OlaMundo.h"

JNIEXPORT void JNICALL Java_jni_OlaMundo_diga (JNIEnv * env, jobject jobj){
printf("Eu sou o metodo nativo >diga<, imprimeindo 'Ola Mundo'.\n");
}
JNIEXPORT void JNICALL Java_jni_OlaMundo_diga2 (JNIEnv * env, jobject jobj){
printf("Eu sou o metodo nativo >diga2<, imprimeindo 'Ola Mundo' tambem.\n");
}
Tudo parece estar correto, mas quando eu executo o código, é executado apenas um metodo da dll, e aparece este erro
Exception in thread "main" java.lang.UnsatisfiedLinkError: jni.OlaMundo.diga2()V
        at jni.OlaMundo.diga2(Native Method)
        at jni.OlaMundo.main(OlaMundo.java:13)
Eu sou o metodo nativo >diga<, imprimeindo 'Ola Mundo'.
Java Result: 1

A minha dll está no C:\Windows\System32

Se alguem puder me ajudar, muito agradecido.

T

Dá a impressão que você tem uma versão antiga da DLL em algum lugar do seu PATH.
Use o utilitário “depends” para saber afinal de contas que símbolos exporta sua DLL.

E

thingol

Obrigado pela dica amigo.

Cheguei em casa, tomei um café, esfriei a cabeça, segui a sua dica e acabei descobrindo que a dll estava sendo compilada com um .h antigo só com um método. Havia dois .h diferentes.

valeu mesmo.

Criado 29 de abril de 2008
Ultima resposta 14 de ago. de 2008
Respostas 35
Participantes 4