Twain JNA

9 respostas
Fox_McCloud

Bom dia.

Estou usando JNA (https://jna.dev.java.net/) para tentar acessar o twain…

Basicamente é a mesma coisa que acessar via JNI (até porque é assim que o JNA acessa), mas o JNAerator (http://code.google.com/p/jnaerator/) já cria toda a estrutura de tipos e acesso às funções c que eu preciso, sem ter que me preocupar em criar o JNI na mão.

O problema é… quando eu tento carregar o twain.dll, recebo a seguinte mensagem de erro (imagino que o twain.dll seja 16 bits):

Loading twain.dll failed (java.lang.UnsatisfiedLinkError: twain.dll: Can’t load this .dll (machine code=0x130) on a IA 32-bit platform)

E quando eu carrego o twain_32.dll e tento acessar uma função (DS_Entry) recebo o seguinte erro:

java.lang.UnsatisfiedLinkError: Error looking up ‘DS_Entry’: Não foi possível encontrar o procedimento especificado.

O JNAerator usa o header do c para criar (em anexo na conversa) as estruturas para o Java… o único detalhe é que o header é da versão 2.1 do twain, as dlls eu não sei.

De qualquer forma a assinatura das duas funções da biblioteca do twain é sempre a mesma, então para eu obter um simples acesso à função não deveria ter problemas…

Por gentileza, qualquer ajuda com o acesso às funções do Twain via Java é bem-vinda.

9 Respostas

J

Fox McCloud:
Bom dia.

Estou usando JNA (https://jna.dev.java.net/) para tentar acessar o twain…

Basicamente é a mesma coisa que acessar via JNI (até porque é assim que o JNA acessa), mas o JNAerator (http://code.google.com/p/jnaerator/) já cria toda a estrutura de tipos e acesso às funções c que eu preciso, sem ter que me preocupar em criar o JNI na mão.

O problema é… quando eu tento carregar o twain.dll, recebo a seguinte mensagem de erro (imagino que o twain.dll seja 16 bits):

Loading twain.dll failed (java.lang.UnsatisfiedLinkError: twain.dll: Can’t load this .dll (machine code=0x130) on a IA 32-bit platform)

E quando eu carrego o twain_32.dll e tento acessar uma função (DS_Entry) recebo o seguinte erro:

java.lang.UnsatisfiedLinkError: Error looking up ‘DS_Entry’: Não foi possível encontrar o procedimento especificado.

O JNAerator usa o header do c para criar (em anexo na conversa) as estruturas para o Java… o único detalhe é que o header é da versão 2.1 do twain, as dlls eu não sei.

De qualquer forma a assinatura das duas funções da biblioteca do twain é sempre a mesma, então para eu obter um simples acesso à função não deveria ter problemas…

Por gentileza, qualquer ajuda com o acesso às funções do Twain via Java é bem-vinda.

esse erro acontece devido a inexistência da função que é acessada, ou no caso o nome pode estar errado. Provavelmente você vai precisar checar o código fonte.
Verifique também se a dll está no path correto.

Fox_McCloud

juliocbq:
esse erro acontece devido a inexistência da função que é acessada, ou no caso o nome pode estar errado. Provavelmente você vai precisar checar o código fonte.
Verifique também se a dll está no path correto.

Então… o path está correto, eu sei que o twain.dll possui essa função, mas ele é 16 bit e não carrega em um Windows 32 bit. Entretanto carregando o twain_32.dll o carregamento da dll ocorre normalmente, mas a aplicação diz que a função não existe…

=P

J

Fox McCloud:
juliocbq:
esse erro acontece devido a inexistência da função que é acessada, ou no caso o nome pode estar errado. Provavelmente você vai precisar checar o código fonte.
Verifique também se a dll está no path correto.

Então… o path está correto, eu sei que o twain.dll possui essa função, mas ele é 16 bit e não carrega em um Windows 32 bit. Entretanto carregando o twain_32.dll o carregamento da dll ocorre normalmente, mas a aplicação diz que a função não existe…

=P

Vai precisar do codigo fonte para checar o nome da função e como ela está sendo exportada( se stdcall ou cdecl). Isso pode gerar esse tipo de problema.

Fox_McCloud
juliocbq:
Vai precisar do codigo fonte para checar o nome da função e como ela está sendo exportada( se stdcall ou cdecl). Isso pode gerar esse tipo de problema.
Bom... no twain.h está assim:
extern "C" {
#endif  /* __cplusplus */

#ifdef TWH_CMP_MSC

  TW_UINT16 FAR PASCAL DS_Entry(pTW_IDENTITY pOrigin,
                                TW_UINT32 DG, 
                                TW_UINT16 DAT, 
                                TW_UINT16 MSG,
                                TW_MEMREF pData);

  typedef TW_UINT16 (FAR PASCAL *DSENTRYPROC)(pTW_IDENTITY pOrigin,
                                              TW_UINT32 DG,
                                              TW_UINT16 DAT,
                                              TW_UINT16 MSG,
                                              TW_MEMREF pData);

#else

  FAR PASCAL TW_UINT16 DS_Entry(pTW_IDENTITY pOrigin,
                                TW_UINT32 DG,
                                TW_UINT16 DAT,
                                TW_UINT16 MSG,
                                TW_MEMREF pData);

  typedef TW_UINT16 (*DSENTRYPROC)(pTW_IDENTITY pOrigin,
                                   TW_UINT32 DG,
                                   TW_UINT16 DAT,
                                   TW_UINT16 MSG,
                                   TW_MEMREF pData);

#endif /* TWH_CMP_MSC */


  typedef TW_HANDLE (PASCAL *DSM_MEMALLOCATE)(TW_UINT32 _size);
  typedef void (PASCAL *DSM_MEMFREE)(TW_HANDLE _handle);
  typedef TW_MEMREF (PASCAL *DSM_MEMLOCK)(TW_HANDLE _handle);
  typedef void (PASCAL *DSM_MEMUNLOCK)(TW_HANDLE _handle);

#ifdef  __cplusplus
}
Lembrando que não tenho o fonte do driver do twain, não é possível, preciso apenas acessá-lo via JNA (JNI).
Fox_McCloud
Ou melhor, o trecho completo da declaração da função no header:
/* Don't mangle the name "DSM_Entry" if we're compiling in C++! */
#ifdef  __cplusplus
extern "C" {
#endif  /* __cplusplus */

#ifdef TWH_CMP_MSC

  TW_UINT16 FAR PASCAL DSM_Entry( pTW_IDENTITY pOrigin,
                                  pTW_IDENTITY pDest,
                                  TW_UINT32    DG,
                                  TW_UINT16    DAT,
                                  TW_UINT16    MSG,
                                  TW_MEMREF    pData);

  typedef TW_UINT16 (FAR PASCAL *DSMENTRYPROC)(pTW_IDENTITY pOrigin,
                                               pTW_IDENTITY pDest,
                                               TW_UINT32 DG,
                                               TW_UINT16 DAT,
                                               TW_UINT16 MSG,
                                               TW_MEMREF pData);

#else

  FAR PASCAL TW_UINT16 DSM_Entry( pTW_IDENTITY pOrigin,
                                  pTW_IDENTITY pDest,
                                  TW_UINT32    DG,
                                  TW_UINT16    DAT,
                                  TW_UINT16    MSG,
                                  TW_MEMREF    pData);

  typedef TW_UINT16 (*DSMENTRYPROC)(pTW_IDENTITY pOrigin, 
                                    pTW_IDENTITY pDest,
                                    TW_UINT32 DG, 
                                    TW_UINT16 DAT, 
                                    TW_UINT16 MSG,
                                    TW_MEMREF pData);

#endif  /* TWH_CMP_MSC */

#ifdef  __cplusplus
}
#endif  /* cplusplus */

/* Don't mangle the name "DS_Entry" if we're compiling in C++! */
#ifdef  __cplusplus
extern "C" {
#endif  /* __cplusplus */

#ifdef TWH_CMP_MSC

  TW_UINT16 FAR PASCAL DS_Entry(pTW_IDENTITY pOrigin,
                                TW_UINT32 DG, 
                                TW_UINT16 DAT, 
                                TW_UINT16 MSG,
                                TW_MEMREF pData);

  typedef TW_UINT16 (FAR PASCAL *DSENTRYPROC)(pTW_IDENTITY pOrigin,
                                              TW_UINT32 DG,
                                              TW_UINT16 DAT,
                                              TW_UINT16 MSG,
                                              TW_MEMREF pData);

#else

  FAR PASCAL TW_UINT16 DS_Entry(pTW_IDENTITY pOrigin,
                                TW_UINT32 DG,
                                TW_UINT16 DAT,
                                TW_UINT16 MSG,
                                TW_MEMREF pData);

  typedef TW_UINT16 (*DSENTRYPROC)(pTW_IDENTITY pOrigin,
                                   TW_UINT32 DG,
                                   TW_UINT16 DAT,
                                   TW_UINT16 MSG,
                                   TW_MEMREF pData);

#endif /* TWH_CMP_MSC */


  typedef TW_HANDLE (PASCAL *DSM_MEMALLOCATE)(TW_UINT32 _size);
  typedef void (PASCAL *DSM_MEMFREE)(TW_HANDLE _handle);
  typedef TW_MEMREF (PASCAL *DSM_MEMLOCK)(TW_HANDLE _handle);
  typedef void (PASCAL *DSM_MEMUNLOCK)(TW_HANDLE _handle);

#ifdef  __cplusplus
}
#endif  /* __cplusplus */
J

extern “C” {

é um padrão para exportar funções de linguagem c, e não c++. Você precisa especificar o padrão correto no mapeamento java. Se é stdcall ou cdecl

dá uma lida aqui, acho que pode te ajudar, apesar de ser c#.

http://bytes.com/topic/net/answers/155407-how-setup-cdecl-callback-c-delagate

Fox_McCloud

juliocbq:
extern “C” {

é um padrão para exportar funções de linguagem c, e não c++. Você precisa especificar o padrão correto no mapeamento java. Se é stdcall ou cdecl

dá uma lida aqui, acho que pode te ajudar, apesar de ser c#.

http://bytes.com/topic/net/answers/155407-how-setup-cdecl-callback-c-delagate


Obrigado, vou olhar sim!

Mas provavelmente o JNAerator detecta isso automaticamente… bom, como ele gera código-fonte aberto eu posso verificar e corrigir se for o caso…

Muito obrigado, sugestões extras continuam bem-vindas!

:wink:

Fox_McCloud

Hum… olhando o header agora é que eu notei o ifdef, e vi também que OU a função DS_Entry vai estar disponível OU a função DSM_Entry vai estar disponível…

E realmente usando o twain_32.dll e chamando a função DSM_Entry a chamada foi nativamente executada… deu erro porque eu enviei tudo nulo ou zerado, só pra testar…

Então, eu creio que esse tópico está RESOLVIDO…!

Valeu!

Twain_32Library.INSTANCE.DSM_Entry(null, null, null, (short)0, (short)0, null);

Extracting jar:file:/C:/Java/Workspaces/Default/JTwain/lib/twain.jar!/libraries/win32/twain_32.dll

A fatal error has been detected by the Java Runtime Environment:

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x48f55016, pid=1248, tid=1400

JRE version: 6.0_14-b08

Java VM: Java HotSpot™ Client VM (14.0-b16 mixed mode windows-x86 )

Problematic frame:

C [twain_32.dll+0x5016]

An error report file with more information is saved as:

C:\Java\Workspaces\Default\JTwain\hs_err_pid1248.log

If you would like to submit a bug report, please visit:

http://java.sun.com/webapps/bugreport/crash.jsp

The crash happened outside the Java Virtual Machine in native code.

See problematic frame for where to report the bug.

jscamara

Fala galera…desenterrando um tópico aki…hehehe…

Estou usando jnaerator tbm…e a lib do twain_32… Como o Fox McCloud disse…ele cria todas as estruturas declaradas no .h do twain…então fica bem simples de trabalhar e passar para a função o que ela precisa…
Mas estou enfrentando um problema… Debugando com o visual studio a minha aplicação java…ele lança várias " First chance Exception - Access Violation". Eu dei uma pesquisada e isso é como se fosse um nullPointer da vida…
E devido a essas exceptions a minha aplicação dá crash… Notei que isso acontece pq o jnaerator trabalha com ponteiros dos endereços de memória…e toda vez que o Garbage Collector passa…ele acaba movendo os objetos da youngGenerator para a oldGenerator área, e os ponteiros dos objetos acabam ficando com o valor desatualizado…

Alguém ja teve um problema semelhante?

Criado 20 de abril de 2010
Ultima resposta 10 de jan. de 2013
Respostas 9
Participantes 3