JNI: Comunicação com DLL proprietária

Boa tarde pessoal,

Tenho uma DLL proprietária que comunica-se com uma balança e preciso extrair informações desta balança (peso, por exemplo) através desta DLL. Dando uma passada pela net achei vários tutoriais sobre JNI, onde os passos para efetuar a comunicação eram: gerar .class, gerar ficheiro .h, criar o arquivo .c baseado no .h e depois gerar a DLL. Contudo, tenho apenas as assinaturas das funções desta DLL (desenvolvida em C). Como posso efetuar esta comunicação? Criei uma espécie de helloworld usando jni tentando comunicar-se com a dll. Pelo que pude perceber, a minha classe java carrega a dll, mas na hora de chamar o método dá erro. Segue abaixo o código seguido do erro. Por favor, alguém me ajude…

public class HelloWorld {
public native Boolean SalvaParametrosBalanca(int Balança, int Modelo,
int Porta, int BaudRate);

static {
	System.loadLibrary("dll/PcScale");
}

public static void main(String[] args) {
	HelloWorld hello = new HelloWorld();
	Boolean teste = hello.SalvaParametrosBalanca(0, 0, 0, 0);
	System.out.println(teste.booleanValue());
}

}

Exception in thread “main” java.lang.UnsatisfiedLinkError: SalvaParametrosBalanca
at HelloWorld.SalvaParametrosBalanca(Native Method)
at HelloWorld.main(HelloWorld.java:12)

Olá amigo,

Num passado remoto eu tive uma duvida bem parecida, e postei aqui.

Mas as noticias não são boas. Dá uma lida:

http://www.guj.com.br/posts/list/23099.java

Um abraço!

Eu recomendo você fazer uma biblioteca (.dll / .so) para mapear / expor as funcionalidades que você precisa, e, então, utilizar o SWIG (google it) para gerar os bindings. JNI é frustrante comparado à interface nativa de outras linguagens, como Python e Lua :cry: .

Olá

Aparentemente este problema é trivial e deve ser resolvido do mesmo modo como acessamos as DLLs do Windows.

Escreva uma DLL em C que acesse a tal DLL proprietária de forma que seja compatível com JNI.

JAVA —> SUA DLL ----> DLL PROPRIETARIA

JAVA <— SUA DLL <---- DLL PROPRIETARIA

[]s
Luca

Valeu pela ajuda galera!
Vou tentar fazer isso mesmo: minha classe -> programa c -> dll proprietária.

Pessoal,

tentei criar essa dll intermediária (shared-object - so - no meu caso), mas encontrei dificuldade.
http://www.guj.com.br/posts/list/73842.java

JAVA -> MINHASO -> SOPROPRIETARIA
JAVA <- MINHASO <- SOPROPRIETARIA

Alguma dica para este caso?

Ola, vc já pensou em esquecer o JNI e tentar utilizar JNA?? É bemmmmm mais facil!
http://jna.dev.java.net/

Com isto vc não vai precisar escrever outra dll em c.

Beleza Abacate,

estou agora tentando usar JNA sim… É realmente muito mais fácil…
MAS (sempre existe um MAS, rsrs),
estou tendo dificuldades em ler um retorno ‘char*’ do c…

estou pegando este retorno como String, mas o String é populado apenas com o primeiro caracter da char*

exemplo:
no c, o cha* é:
“Abacate”

no Java fica:
“A”

estou agora tentando mudar o meu .c para .cpp para assim poder usar AnsiString por exemplo…

alguma idéia?

Me interessei pelo tópico.

Mas infelizmente não tenho nada para acrescentar, pelo contrário, tenho mais dúvidas. Por exemplo, com o JNA eu consigo invocar um método de uma DLL proprietária, é isso?

No caso do retorno desse método ser um Recordset do VB, como fica a interpretação?

Estou realmente muito interessado nisso!

Um abraço à todos.

felipeguerra,

sim, com JNA é possível acessar diretamente rotinas que estão dentrou de um SO (ou DLL). Em relação ao ‘Recordset do VB’ não posso te ajudar…

Pessoal,

Desculpe perguntar, mas não existiria um material mais didático sobre JNA do que o apresentado no site https://jna.dev.java.net/?

mais didatico?

http://www.urubatan.com.br/chamando-metodos-nativos-dllso-em-java-sem-jni/

Olha só pessoal,

Efetuei o seguinte teste:

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface Balanca extends Library {

Balanca INSTANCE = (Balanca) Native.loadLibrary("dll/PcScale", Balanca.class);

boolean InicializaBalanca(int balanca);

}

public class BalancaImpl implements Balanca {

public boolean InicializaBalanca(int balanca) {
	
	Balanca dll = Balanca.INSTANCE;
	boolean teste = dll.InicializaBalanca(0);
	return teste;
}

}

Mas quando tento chamar o método em uma classe de teste dá o seguinte erro:

Exception in thread “main” java.lang.UnsatisfiedLinkError: Cannot locate function ‘InicializaBalanca’
at com.sun.jna.NativeLibrary.getFunctionAddress(NativeLibrary.java:228)
at com.sun.jna.Function.(Function.java:143)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:212)
at com.sun.jna.Library$Handler.invoke(Library.java:165)
at $Proxy0.InicializaBalanca(Unknown Source)
at BalancaImpl.InicializaBalanca(BalancaImpl.java:7)
at TestaDLL.main(TestaDLL.java:5)

Dentro do meu projeto no eclipse existe a pasta dll onde está a dll da qual desejo usar as funções.

Pessoas,

Acho que já tenho a resposta para a minha pergunta…
Vasculhando os arquivos dessa dll proprietária, encontrei o arquivo .h dela. No .h, o método boolean InicializaBalanca(int balanca) está com a seguinte estrutura:

#ifdef DLLCODE
#define PCSCALEAPI WINAPI _export
#define PCSCALECALL
#else
#define PCSCALEAPI WINAPI
#define PCSCALECALL extern
#endif

// Novas Rotinas para leitura da balança
PCSCALECALL bool PCSCALEAPI InicializaLeitura(int balanca);

Como posso representar esta estrutura em um método de minha interface java? Vale ressaltar que não conheço C e seus derivados… :slight_smile:

Pessoas,

Problema Resolvido! Na verdade o problema estava entre o monitor e a cadeira! :stuck_out_tongue: O manual da DLL que eu estava usando era antigo. Quando verifiquei o arquivo .h da DLL percebi isso. A assinatura do método estava errada. Quando setei, na minha interface java, a assinatura do método com base no arquivo .h deu certo!
JNA é muito mais simples mesmo! Obrigado a todos!

Pessoal também estou utilizando JNA, será que alguém ai pode me dar uma ajuda com este post.

http://www.guj.com.br/posts/list/79338.java