Página 1 de 2
Função CallDLL
Enviado: 12 Dez 2007 11:46
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"
Enviado: 12 Dez 2007 15:35
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
Enviado: 12 Dez 2007 16:10
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...
Enviado: 12 Dez 2007 16:45
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)
Enviado: 12 Dez 2007 16:48
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.
Enviado: 12 Dez 2007 17:13
por Dércio_Luiz_Zanatta
Cara..
Qual o comando da DLL que está dando problema ai...
quero dar uma simulada aqui...
Enviado: 12 Dez 2007 17:19
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
Enviado: 12 Dez 2007 17:25
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.
Chamando uma dll... falhas no DllCall
Enviado: 12 Dez 2007 17:46
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!
Enviado: 13 Dez 2007 08:45
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...
Enviado: 13 Dez 2007 10:42
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
Não foi ainda desta vez...
Enviado: 13 Dez 2007 13:04
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!
Uma luz no fim do túnel?
Enviado: 13 Dez 2007 13:20
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
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!
Traduzindo código em C
Enviado: 13 Dez 2007 14:08
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]
Enviado: 13 Dez 2007 16:00
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