Função CallDLL

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

celo.michels
Usuário Nível 1
Usuário Nível 1
Mensagens: 27
Registrado em: 19 Nov 2007 11:33
Localização: Feira de Santana

Função CallDLL

Mensagem por celo.michels »

Ola amigos
Estou tentando usar a função calldll
estou fazendo da seguinte forma

Código: Selecionar todos

var := função na dll         
hDLL     := DllLoad( "BEMAFI32.DLL" )         
cFarProc := GetProcAddress( hDLL, VAR )         
uResult  := CallDLL(cFarProc,"Parametro")         
DLLunload( hDLL ) 
Quando nao existe nenhum parametro blz passa normal.
Ja quando tenho parametro o sistema aborta sem erro nenhum.
Alguem sabe como e onde coloco os parametro?????

Marcelo Michels
marcelo@infototal.com.br
"Total Informatica"
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Mensagem por rodrmigu »

Olá,

Eu particularmente nao gosto de usar a calldll, tem algumas limitações, não me lembro quais, que me levaram a usar rotinas em C diretamente. Segue um exemplo do que eu tenho usado, vc verá que é bem simples:

Código: Selecionar todos

#if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__)

#include "hbapi.h"
#include "windows.h"

typedef INT   (WINAPI *_FASTREPORTDBF)   ( HWND hwnd, LPSTR lpFileName, LPSTR lpReportName );
typedef INT   (WINAPI *_FASTREPORTSQL)   ( HWND hwnd, LPSTR lpQuery, LPSTR lpReportName, LPSTR lpHost, LPSTR lpDatabase, LPSTR lpUser, LPSTR lpPass, LPSTR lpProtocol );
typedef LPSTR (WINAPI *_FASTREPORTDESIGN)( HWND hwnd, LPSTR lpQuery, LPSTR lpReportName, LPSTR lpHost, LPSTR lpDatabase, LPSTR lpUser, LPSTR lpPass, LPSTR lpProtocol );
typedef INT   (WINAPI *_SHOWPREVIEW)     ( HWND hwnd, LPSTR lpText, INT bMatrix );
typedef LPSTR (WINAPI *_REPORTVERSION)   ( void );

HB_FUNC( FASTREPORTDBF )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _FASTREPORTDBF pFunc;
        pFunc = (_FASTREPORTDBF) GetProcAddress(handle, "FastReportDBF");
        hb_retni(pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), ( LPSTR ) hb_parcx(3) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( FASTREPORTSQL )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _FASTREPORTSQL pFunc;
        pFunc = (_FASTREPORTSQL) GetProcAddress(handle, "FastReportSQL");
        hb_retni(pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), ( LPSTR ) hb_parcx(3), ( LPSTR ) hb_parcx(4), ( LPSTR ) hb_parcx(5), ( LPSTR ) hb_parcx(6), ( LPSTR ) hb_parcx(7), ( LPSTR ) hb_parcx(8) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( FASTREPORTDESIGN )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _FASTREPORTDESIGN pFunc;
        pFunc = (_FASTREPORTDESIGN) GetProcAddress(handle, "FastReportDesign");
        hb_retc( ( LPSTR ) pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), ( LPSTR ) hb_parcx(3), ( LPSTR ) hb_parcx(4), ( LPSTR ) hb_parcx(5), ( LPSTR ) hb_parcx(6), ( LPSTR ) hb_parcx(7), ( LPSTR ) hb_parcx(8) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( SHOWPREVIEW )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _SHOWPREVIEW pFunc;
        pFunc = (_SHOWPREVIEW) GetProcAddress(handle, "ShowPreview");
        hb_retni(pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), hb_parni(3) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( REPORTVERSION )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _REPORTVERSION pFunc;
        pFunc = (_REPORTVERSION) GetProcAddress(handle, "ReportVersion");
        hb_retc( ( LPSTR ) pFunc() );
        FreeLibrary( handle );
    }
}

#endif
[]'s
Rodrigo
Dércio_Luiz_Zanatta
Usuário Nível 3
Usuário Nível 3
Mensagens: 153
Registrado em: 11 Jan 2006 15:37
Localização: Ibirubá - RS

Mensagem por Dércio_Luiz_Zanatta »

Caro colega..
Tente usar dessa forma:
NDLL:=LoadLibrary("MinhaDLL.dll")
DLLCALL(NDLL,32,"Função da DLL",Parametro1,parametro2,..)
FreeLibrary(NDLL)
Eu uso assim para acessar a DLL das impressoras Urano e Perto e funciona maravilhosamente bem...
Qualquer dúvida, prende o grito ai...
celo.michels
Usuário Nível 1
Usuário Nível 1
Mensagens: 27
Registrado em: 19 Nov 2007 11:33
Localização: Feira de Santana

Mensagem por celo.michels »

No meu caso seria com a DLL da Bematech.
estou fazendo assim mas nao esta funcionando.
Var seria a Funcao na dll
PRMT seria os parametros caso exista.

Código: Selecionar todos

         hDLL :=LoadLibrary("BEMAFI32.DLL" )
         IF prmt <> nil
            func := {&prmt}
            FOR xPOS:= 1 TO len(func)
               _xPOS:=strzero(xPOS,2)
               PAR&_xPOS := func[xPOS]
            NEXT
// Nenhuma das duas formas funciona
            //uResult := DLLCALL(hDLL,32,VAR,PAR01,9,PAR02,9,PAR03,9) 
            uResult := DLLCALL(hDLL,32,VAR,PAR01,PAR02,PAR03) 
            FOR xPOS:= 1 TO len(func)
               _xPOS:=strzero(xPOS,2)
               func[xPOS]:= PAR&_xPOS 
            NEXT
         ELSE
            uResult := DLLCALL(hDLL,32,VAR) 
            //uResult  := CallDLL(cFarProc)
         ENDIF
         FreeLibrary(hDLL) 
celo.michels
Usuário Nível 1
Usuário Nível 1
Mensagens: 27
Registrado em: 19 Nov 2007 11:33
Localização: Feira de Santana

Mensagem por celo.michels »

rodrmigu escreveu:Olá,

Eu particularmente nao gosto de usar a calldll, tem algumas limitações, não me lembro quais, que me levaram a usar rotinas em C diretamente. Segue um exemplo do que eu tenho usado, vc verá que é bem simples:

Código: Selecionar todos

#if defined(_WIN32) || defined(WIN32) || defined(__MINGW32__)

#include "hbapi.h"
#include "windows.h"

typedef INT   (WINAPI *_FASTREPORTDBF)   ( HWND hwnd, LPSTR lpFileName, LPSTR lpReportName );
typedef INT   (WINAPI *_FASTREPORTSQL)   ( HWND hwnd, LPSTR lpQuery, LPSTR lpReportName, LPSTR lpHost, LPSTR lpDatabase, LPSTR lpUser, LPSTR lpPass, LPSTR lpProtocol );
typedef LPSTR (WINAPI *_FASTREPORTDESIGN)( HWND hwnd, LPSTR lpQuery, LPSTR lpReportName, LPSTR lpHost, LPSTR lpDatabase, LPSTR lpUser, LPSTR lpPass, LPSTR lpProtocol );
typedef INT   (WINAPI *_SHOWPREVIEW)     ( HWND hwnd, LPSTR lpText, INT bMatrix );
typedef LPSTR (WINAPI *_REPORTVERSION)   ( void );

HB_FUNC( FASTREPORTDBF )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _FASTREPORTDBF pFunc;
        pFunc = (_FASTREPORTDBF) GetProcAddress(handle, "FastReportDBF");
        hb_retni(pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), ( LPSTR ) hb_parcx(3) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( FASTREPORTSQL )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _FASTREPORTSQL pFunc;
        pFunc = (_FASTREPORTSQL) GetProcAddress(handle, "FastReportSQL");
        hb_retni(pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), ( LPSTR ) hb_parcx(3), ( LPSTR ) hb_parcx(4), ( LPSTR ) hb_parcx(5), ( LPSTR ) hb_parcx(6), ( LPSTR ) hb_parcx(7), ( LPSTR ) hb_parcx(8) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( FASTREPORTDESIGN )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _FASTREPORTDESIGN pFunc;
        pFunc = (_FASTREPORTDESIGN) GetProcAddress(handle, "FastReportDesign");
        hb_retc( ( LPSTR ) pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), ( LPSTR ) hb_parcx(3), ( LPSTR ) hb_parcx(4), ( LPSTR ) hb_parcx(5), ( LPSTR ) hb_parcx(6), ( LPSTR ) hb_parcx(7), ( LPSTR ) hb_parcx(8) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( SHOWPREVIEW )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _SHOWPREVIEW pFunc;
        pFunc = (_SHOWPREVIEW) GetProcAddress(handle, "ShowPreview");
        hb_retni(pFunc( ( HWND ) hb_parnl(1), ( LPSTR ) hb_parcx(2), hb_parni(3) ));
        FreeLibrary( handle );
    }
}

HB_FUNC( REPORTVERSION )
{
    HINSTANCE handle = LoadLibrary("report.dll");

    if (handle)
    {
        _REPORTVERSION pFunc;
        pFunc = (_REPORTVERSION) GetProcAddress(handle, "ReportVersion");
        hb_retc( ( LPSTR ) pFunc() );
        FreeLibrary( handle );
    }
}

#endif
[]'s
Rodrigo
Cara não entendi nada.
Tb nao sei nada de C.
Dércio_Luiz_Zanatta
Usuário Nível 3
Usuário Nível 3
Mensagens: 153
Registrado em: 11 Jan 2006 15:37
Localização: Ibirubá - RS

Mensagem por Dércio_Luiz_Zanatta »

Cara..
Qual o comando da DLL que está dando problema ai...
quero dar uma simulada aqui...
Avatar do usuário
janio
Colaborador
Colaborador
Mensagens: 1846
Registrado em: 06 Jul 2004 07:43
Localização: UBAJARA - CE

Mensagem por janio »

Por mais de uma vez foi postado no news do xharbour (cole 'xHarbour.Spanish.Portuguese' no seu navegador) um arquivo .c (dllbemac.c) para comunicação com a dll da bematech que funciona perfeitamente.

Jânio
fui...
e-mail:janioaguiar@yahoo.com.br
msn: janio_aguiar@hotmail.com
xHarbour1.2.1/Harbour3.2 + wvg + hwgui + Mediator + MySql
celo.michels
Usuário Nível 1
Usuário Nível 1
Mensagens: 27
Registrado em: 19 Nov 2007 11:33
Localização: Feira de Santana

Mensagem por celo.michels »

janio escreveu:Por mais de uma vez foi postado no news do xharbour (cole 'xHarbour.Spanish.Portuguese' no seu navegador) um arquivo .c (dllbemac.c) para comunicação com a dll da bematech que funciona perfeitamente.

Jânio
**
Se existe comunicação com dll então tem que funcionar.
paulobergo
Usuário Nível 1
Usuário Nível 1
Mensagens: 30
Registrado em: 09 Nov 2007 08:54
Localização: Juiz de Fora-MG

Chamando uma dll... falhas no DllCall

Mensagem por paulobergo »

Ola...
Demorei tanto a postar um tópico sobre como chamar uma dll que quando enviei já havia este...
Mas vamos lá...

Criei uma dll bem simples no Delphi:

Código: Selecionar todos

Library FazNada;

Uses
  FastShareMem,
  SysUtils,
  Classes;

{$R *.res}

Function sNadaFaz(sNada: String): String; Export;
Begin
  sNadaFaz := 'nadafeito';
End;
Exports sNadaFaz;

Begin
End.
Gostaria de poder chamá-la... então, coloquei algumas linhas como nos exemplos que vocês citaram:

Código: Selecionar todos

NDLL := LoadLibrary("d:\download\sia\FazNada.dll") 
DLLCALL(NDLL,32,"sNadaFaz","siajf")
FreeLibrary(NDLL) 
Mas, ao tentar executar, o programa paralisa e falha na linha do comando DllCall...

Alguma idéia?

Grato! Abraços!
Não se vê bem com insolação... é essencial cobrir os olhos...
Dércio_Luiz_Zanatta
Usuário Nível 3
Usuário Nível 3
Mensagens: 153
Registrado em: 11 Jan 2006 15:37
Localização: Ibirubá - RS

Mensagem por Dércio_Luiz_Zanatta »

Caro colega...
No caso da Bemafi32.dll, existe um conveniência quanto a funções que retornam algum valor numérico em um ou mais parâmetros.
Por isso o problema ocorre com a função Bematech_FI_RetornoImpressora(Ack,Vst1,Vst2).
Pelo que pude ver, os retornos sempres são caracteres e quando retornam números, eles vem em código ASC.

Tente fazer assim:

Vask:=space(1)
Vst1:=Space(1)
Vst2:=Space(2)
DllCall(Ndll,32,"Bematech_FI_RetornoImpressora,vack,vst1,vst2)
? asc(vack)
? asc(vst1)
? asc(vst2)

Espero ter ajudado..
Um grande abraço...
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Mensagem por rodrmigu »

Olá,
paulobergo escreveu: Mas, ao tentar executar, o programa paralisa e falha na linha do comando DllCall...
Os tipos de dados precisam ser diferentes:

Código: Selecionar todos

Library FazNada;

Uses
  FastShareMem,
  SysUtils,
  Classes;

{$R *.res}

Function sNadaFaz(sNada: PChar; num: integer): PChar; StdCall;
Begin
   showmessage(StrPas(sNada));
   showmessage(IntToStr(num));
   result := PChar('nadafeito');
End;

Begin
End. 
Dai eu faço a chamada do xharbour assim:

Código: Selecionar todos

Procedure Main()
	? NadaFaz('Hello World', 123456)
return


#PRAGMA BEGINDUMP

#include "hbapi.h"
#include "windows.h"

typedef LPSTR (WINAPI *_SNADAFAZ)   	( LPSTR snada, INT num );

HB_FUNC( NADAFAZ )
{
    HINSTANCE handle = LoadLibrary("minhadll.dll");

    if (handle)
    {
        _SNADAFAZ pFunc;
        pFunc = (_SNADAFAZ) GetProcAddress(handle, "sNadaFaz");
        hb_retc( (LPSTR) pFunc( ( LPSTR ) hb_parcx(1), hb_parni(2) ));
        FreeLibrary( handle );
    }
}

#PRAGMA ENDDUMP
[]'s
Rodrigo
paulobergo
Usuário Nível 1
Usuário Nível 1
Mensagens: 30
Registrado em: 09 Nov 2007 08:54
Localização: Juiz de Fora-MG

Não foi ainda desta vez...

Mensagem por paulobergo »

Bom... ainda não foi desta vez...

A seguinte chamada à uma dll funciona perfeitamente:

Código: Selecionar todos

DLLCall("WINMM.DLL",32,"sndPlaySoundA", "Inicialização do Windows XP.wav", 0 ) 
* Toca o som do Windows, numa boa...

Agora a minha dll "FazNada", se chamada de um programa do Delphi ou do VB, funciona perfeitamente... (se a cláusula Export for declarada como visto abaixo):

Código: Selecionar todos

Library FazNada;

Uses
  FastShareMem,
  SysUtils,
  Classes,
  Windows, Dialogs;

{$R *.res}

// Sem Export, falha ao ser chamada por outra aplicação Delphi ou VB
// Function sNadaFaz(sNada: PChar; num: Integer): PChar; StdCall;
Function sNadaFaz(sNada: PChar; num: Integer): PChar; Export;
Var
  slTemp: TStringList;
Begin
  slTemp := TStringList.Create;
  slTemp.Add('Isso foi gravado pela dll...');
  slTemp.Add('Os parametro recebidos do clipper foram:');
  slTemp.Add('sNada='+sNada);
  slTemp.Add('num='+IntToStr(num));
  slTemp.SaveToFile('c:\temp\issoisso.txt');
  ShowMessage(StrPas(sNada));
  ShowMessage(IntToStr(num));
  result := PChar('nadafeito');
End;
Exports sNadaFaz;
//

Begin
End.
Quanto à função em C, compilou corretamente mas retorna Nil...

De qualquer forma, continuo tentando desvendar o mistério...

Grato... Abraços!
Não se vê bem com insolação... é essencial cobrir os olhos...
paulobergo
Usuário Nível 1
Usuário Nível 1
Mensagens: 30
Registrado em: 09 Nov 2007 08:54
Localização: Juiz de Fora-MG

Uma luz no fim do túnel?

Mensagem por paulobergo »

Caro Rodrmigu e colegas!

A rotina em C deu certo!!! foi só preciso mover a dll da pasta da aplicação principal para a pasta windows\system32...

Isso:

Código: Selecionar todos

HINSTANCE handle = LoadLibrary("D:\DOWNLOAD\SIA\FAZNADA.DLL"); 
Não funcionou

mas

Código: Selecionar todos

HINSTANCE handle = LoadLibrary("FAZNADA.DLL"); 
deu certo...

Claro... se houver uma forma de "forçar" a busca da dll diretamente da pasta onde está a aplicação principal... seria bem melhor...

Outra Coisa... passar parâmetros para a dll, sem problema... mas como receber algum resultado de volta? um simples False ou True, 0 ou 1... tem jeito?

Meu problema é que em matéria de C, sou um Cero à esquerda...

De qualquer forma, grato pela colaboração!!!

Abraços!
Não se vê bem com insolação... é essencial cobrir os olhos...
paulobergo
Usuário Nível 1
Usuário Nível 1
Mensagens: 30
Registrado em: 09 Nov 2007 08:54
Localização: Juiz de Fora-MG

Traduzindo código em C

Mensagem por paulobergo »

A/C Rodrmigu

Tentando traduzir o código em C que você disponibilizou, para poder criar outras funções, seria mais ou menos isso:?

Código: Selecionar todos

#PRAGMA BEGINDUMP 

#include "hbapi.h" 
#include "windows.h" 

typedef LPSTR (WINAPI *_SNADAFAZ)      ( LPSTR snada, INT num ); 
Definir tipos: 
        SNADAFAZ = Função, chamada por uma API do Windows, do tipo LPSTR
        snada = Variável também LPSTR requerida pela função
        num = Variável Inteiro requerida pela função

HB_FUNC( NADAFAZ ) 
Define uma função para ser chamada em qualquer ponto da aplicação

{ 
    HINSTANCE handle = LoadLibrary("minhadll.dll"); 
                 n                       o
    cria um controlador para carregar e acessar a dll

    if (handle) // Se a dll foi carregada, então executar a função.
    { 
        _SNADAFAZ pFunc;
            a       b
           cria um Ponto de acesso (b) para a função desejada (a)

        pFunc = (_SNADAFAZ) GetProcAddress(handle, "sNadaFaz");
           c         d            e           f         g
                            // Obtem, para o "ponto" (b), o endereço (e) da função  (g)

        hb_retc( (LPSTR) pFunc( ( LPSTR ) hb_parcx(1), hb_parni(2) )); 
           m        h      i        j          k            l
          - passa os parâmetros (k, l) para a função da dll
          - obtem o retorno (por m) da função (g) em formato LPSTR (j) e retorna, para o
            programa, também um conteúdo LPSTR (j)

        FreeLibrary( handle ); 
                        p
        libera, da memória, o controlador (n) da dll carregada.
    } 
} 

#PRAGMA ENDDUMP 
 
[/code]
Não se vê bem com insolação... é essencial cobrir os olhos...
rodrmigu
Usuário Nível 3
Usuário Nível 3
Mensagens: 150
Registrado em: 27 Nov 2007 15:13
Localização: Indaiatuba SP

Mensagem por rodrmigu »

Está correto.

Na linha:
typedef LPSTR (WINAPI *_SNADAFAZ) ( LPSTR snada, INT num );

é o que chamamos de prototipagem, neste caso como não existe uma funcão real, ela acaba sendo por ponteiros, por isso a chamada logo abaixo no código é mais esquisita.

Em relação ao retorno, dá sim. Acima, o retorno é um pointeiro de string, se quiser 0/1, troque por INT e no corpo da função onde vc vê o hb_retc, que retorna char, voce usaria um hb_retni, ou para logico, hb_retl.

[]'s
Rodrigo
Responder