Twain JNA

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.

[quote=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.[/quote]

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.

[quote=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.
[/quote]
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

[quote=Fox McCloud][quote=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.
[/quote]
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[/quote]

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:

[code]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
}[/code]
Lembrando que não tenho o fonte do driver do twain, não é possível, preciso apenas acessá-lo via JNA (JNI).

Ou melhor, o trecho completo da declaração da função no header:

[code]/* 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 */[/code]

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

[quote=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[/quote]
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:

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.

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?