Selecao DevMedia QUERO SER PRIME

Fórum Ainda a tal da DLL - Vejam se isso está correto #349547

23/11/2007

0

[color=red:d3b888c298]Este é o código de uma função dentro de uma DLL que eu criei para teste:[/color:d3b888c298]

[b:d3b888c298]unit CpsFunc;

interface

uses

ShareMem, SysUtils, Windows;

var


function VCpf(ParVcpf : string) : string; overload;
var
CpfNew : String;
MultVcpf : Integer;
SomaVcpf : Integer;
lk : Integer;
DpVcpf : Integer;
Digito : String;
begin

if (length(trim(ParVcpf))<11) or (ParVcpf=´00000000000´) or (ParVcpf=´99999999999´) then;
Result := ´F´;

CpfNew := Copy(ParVcpf,1,9);
MultVcpf := 2;
SomaVcpf := 0;

for lk := 9 downto 1 do
begin
SomaVcpf := SomaVcpf + (MultVcpf * StrToInt(Copy(CpfNew,lk,1)));
MultVcpf := MultVcpf + 1;
end;

SomaVcpf := SomaVcpf * 10;
DpVcpf := SomaVcpf-(SomaVcpf mod 11);

if DpVcpf = 10 then
Digito := ´0´;
if DpVcpf < 10 then
Digito := IntToStr(DpVcpf);

CpfNew := CpfNew + Digito;

MultVcpf := 2;
SomaVcpf := 0;

for lk := 10 downto 1 do
begin
SomaVcpf := SomaVcpf + (MultVcpf * StrToInt(Copy(CpfNew,lk,1)));
MultVcpf := MultVcpf + 1;
end;

SomaVcpf := SomaVcpf * 10;
DpVcpf := SomaVcpf-(SomaVcpf mod 11);
if DpVcpf = 10 then
Digito := ´0´;
if DpVcpf < 10 then
Digito := IntToStr(DpVcpf);

CpfNew := CpfNew + Digito;

if CpfNew = ParVcpf then
Result := ´V´
else
Result := ´F´

end;
end.[/b:d3b888c298]

[color=red:d3b888c298]Este é o código de um projeto que fiz para tentar ´chamar´ a função da DLL:[/color:d3b888c298]

[b:d3b888c298]unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
ButtonChecar: TButton;
procedure ButtonChecarClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
NCpf : string;

implementation

{$R *.dfm}

function VCpf(ParVcpf : string) : string; stdcall; external ´CpsFunc.DLL´;


procedure TForm1.ButtonChecarClick(Sender: TObject);
begin
NCpf := Edit1.Text;
if VCpf(NCpf) = ´V´ then
Edit2.Text := ´Verdadeiro´;
if VCpf(NCpf) = ´F´ then
Edit2.Text := ´Falso´;
end;

end.[/b:d3b888c298]

[color=red:d3b888c298]Na compilação não dá erro, mas ao tentar executar dá o seguinte erro:[/color:d3b888c298]

[b:d3b888c298]Aplicativo não inicializado corretamente (0xc000007b). Clique em ´OK´ para finalizar a execução.[/b:d3b888c298]

[color=red:d3b888c298]Gostaria que alguem me esclarecesse o que pode (e deve) estar errado nesses códigos.[/color:d3b888c298]


Cps.art

Cps.art

Responder

Posts

24/11/2007

Werlon Goulart

A Estrutura está errada...
Uma DLL não tem Unit... Tem Library....

Use o proprio Delphi pra criar a estrutura da DLL
em File>>New>>Other selecione ´DLL Wizard´....

Ai é so colar dentro sua Função e declarar corretamente o Retorno dela...
Notei q vc não fez isso...
Para declarar o retorno da DLL use no final dela :

Exports Nome_da_funcao;

Grande abraço
Werlon Goulart


Um exemplo de uma DLL inteira:

//------------------------------------------------------------------------------------------------------------------//
//------------------------------------------------------------------------------------------------------------------//
// Desenvolvido por : Werlon Goulart em: 03/09/2007. //
//------------------------------------------------------------------------------------------------------------------//
// Objetivo: //
// Criptografa - Criptografa/Descriptografa no mesmo padrão usado pelos sistemas xxx e yyy. //
// O Caracter Asterisco no Inicio da Senha indica que vai descriptografar pois já está //
// criptografado.
// Parâmetro : Chave = String Única que impede que outras aplicações executem a função sem permissão. //
// Retorno : OK = String Criptografada com os Identificadores. //
//------------------------------------------------------------------------------------------------------------------//
Library teste;

Uses
Windows, SysUtils, Classes;

//Criptografa/Descriptografa no mesmo padrão usado pelos sistemas xxx e yyy.
//O Caracter Asterisco no Inicio da Senha indica que vai descriptografar pois já está criptografado.
Function Criptografa(Senha: String): String;
Var I: Integer;
Texto : String;
S: String[255];
C: Array[0..255] of Byte Absolute S;
begin
if Copy(Senha, 1, 1) = ´*´ then begin
Senha := Copy(Senha, 1, Length(Senha));
end;

S := Senha;
For I:=1 to Length(Senha) do begin
if Copy(Senha, 1, 1) = ´*´ then begin
Texto := Texto + Char(Ord(C[I]) Div 2);
end
else begin
Texto := Texto + Char(Ord(C[I]) * 2);
end;
if Copy(Senha, 1, 1) = ´*´ then begin
Result := Copy(Texto, 2, Length(Texto) - 1);
end
else begin
Result := ´*´ + Texto;
end;
end;
end;


//Torna as Funções Visiveis Externamente e Faz o Retorno para o Identificador.
Exports Criptografa;
end.


Responder

Gostei + 0

24/11/2007

Cps.art

Obrigado Werlon.

Eu transcrevi por engano o .PAS da DLL, mas na verdade o código dela é esse aí embaixo:

[color=blue:7bc96d3da7]library CpsFunc;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library´s USES clause AND your project´s (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
SysUtils,
Classes,
ShareMem;

{$R *.res}


function VCpf(ParVcpf : string) : string; stdcall; overload;
var
CpfNew : String;
MultVcpf : Integer;
SomaVcpf : Integer;
lk : Integer;
DpVcpf : Integer;
Digito : String;
begin

if (length(trim(ParVcpf))<11) or (ParVcpf=´00000000000´) or (ParVcpf=´99999999999´) then;
Result := ´F´;

CpfNew := Copy(ParVcpf,1,9);
MultVcpf := 2;
SomaVcpf := 0;

for lk := 9 downto 1 do
begin
SomaVcpf := SomaVcpf + (MultVcpf * StrToInt(Copy(CpfNew,lk,1)));
MultVcpf := MultVcpf + 1;
end;

SomaVcpf := SomaVcpf * 10;
DpVcpf := SomaVcpf-(SomaVcpf mod 11);

// dpvcpf=somavcpf-((int(somavcpf/11))*11)

if DpVcpf = 10 then
Digito := ´0´;
if DpVcpf < 10 then
Digito := IntToStr(DpVcpf);

CpfNew := CpfNew + Digito;

MultVcpf := 2;
SomaVcpf := 0;

for lk := 10 downto 1 do
begin
SomaVcpf := SomaVcpf + (MultVcpf * StrToInt(Copy(CpfNew,lk,1)));
MultVcpf := MultVcpf + 1;
end;

SomaVcpf := SomaVcpf * 10;
DpVcpf := SomaVcpf-(SomaVcpf mod 11);
if DpVcpf = 10 then
Digito := ´0´;
if DpVcpf < 10 then
Digito := IntToStr(DpVcpf);

CpfNew := CpfNew + Digito;

if CpfNew = ParVcpf then
Result := ´V´
else
Result := ´F´

end;
end.[/color:7bc96d3da7]

Você deve ter percebido que é uma rústica rotina de checagem de CPF.
Se eu acrescentar a linha ´exports´ que você sugeriu, a forma como eu tento usar essa função no meu Projeto Teste (a segunda unit que enviei anteriormente), está correta?
Por exemplo a linha de comando:

[color=blue:7bc96d3da7]if VCpf(NCpf) = ´V´ then[/color:7bc96d3da7]

Essa comparação está correta?

Na função da DLL eu determinei [b:7bc96d3da7]Result := ´V´ ou Result := ´F´[/b:7bc96d3da7]

É assim mesmo ou tenho que mudar?

Obrigado


Responder

Gostei + 0

24/11/2007

Massuda

ShareMem tem que ser a primeira unit no uses tanto da DLL como do DPR do programa que usa a DLL.


Responder

Gostei + 0

24/11/2007

Cps.art

OK Massuda, isso já foi feito.

Agora tá dando o seguinte erro:

[b:55e4ff7a88]Project Project1.exe raised exception class EConvertError with message ´´´ is not a valid integer value´. Process stopped. Use step or run to continue[/b:55e4ff7a88].

Acho que o erro é na função na DLL, apesar que a linha selecionada na ocasião do erro seja na unit da Rotina que ´chama´ a função, especificamente a linha [b:55e4ff7a88]if VCpf(NCpf) = ´V´ then[/b:55e4ff7a88] quando se executa a partir do Run do Delphi.

Quando se executa a partir do .EXE da rotina, ou seja, a rotina já compilada, o erro é o seguinte:

[b:55e4ff7a88]Exception EConvertError in module CpsFunc.DLL at 000074E2.[/b:55e4ff7a88]

Conhece aquele ditado ´De grão em grão a galinha enche o papo´?

Comigo já é assim: ´De erro em erro o cps.art enche o saco´

Acho que vou acabar voltando para o Clipper mesmo.

Obrigado pela ajuda pessoal.
Fico aguardando mais algumas dicas.


Responder

Gostei + 0

24/11/2007

Werlon Goulart

Massuda,
O Sharemem deve ser declarado se forem passados como Retorno Strings Longas ou Arrays da DLL para o Chamador.

Eu tenho algumas DLL´s que uso até no PowerBuilder(SyBase) pois esta linguagem não dá suporte a algumas facilidades, e não uso o ShareMem em nenhuma delas...

No PowerBuilder até faço a criação da Instância da DLL dinamicamente sem problemas.

Claro estou falando do Delphi7, nas versões mais novas não sei dizer... Tô la atrás... he he he....

Grande Abraço
Werlon Goulart


Responder

Gostei + 0

24/11/2007

Werlon Goulart

Achei o Erro...
Vc tá passando de volta uma string e DLL´s devem passar PChar, que é o tipo de dado que o Windows trabalha.

Troque :

//function VCpf(ParVcpf : string) : string; stdcall; overload;
function VCpf(ParVcpf : string) : PCHAR; stdcall; overload;


if CpfNew = ParVcpf then
//Result := ´V´
Result := PChar(´V´);
end
else begin
//Result := ´F´
Result := PChar(´F´)
end;

//Assim vc trafega entre a DLL e sua Aplicação o Tipo PChar.

Na Aplicação que recebe o retorno Troque:
//if VCpf(NCpf) = ´V´ then
if String(VCpf(NCpf)) = ´V´ then

Mais uma coisa... Não entendi pra que o Overload se vc não vai sobrescrever nenhum metódo ???

Grande abraço
Werlon Goulart


Responder

Gostei + 0

25/11/2007

Cps.art

Pois bem meus amigos, descobri que o erro que está dando não é só pelo fato da função estar dentro da DLL.

Resolvi primeiro ver se a função realmente funcionava e a coloquei dentro de meu Projeto Teste e deu o mesmo erro.

Pelas dicas que o Werlon deu já percebi isso.
Vou alterar e tentar fazer com que essa função funcione dentro do próprio projeto, aí depois vou coloca-la na DLL.

Quanto a estar usando o [b:3de4417968]overload[/b:3de4417968] é que não conheço praticamente nada de funções no Delphi, estou iniciando, e vou pegando exemplos por aí e tentando.

Vou fazer as alterações e depois posto uma mensagem sobre o resultado.

Um grande abraço aos amigos colaboradores.


Responder

Gostei + 0

25/11/2007

Cps.art

Pois é amigos, o erro está na função em si.

Coloquei a função num Projeto e tentei numa Edit entrar com o CPF e clicando num botão, uma outra Edit me mostraria se é ´Verdadeiro´ ou ´Falso´, mas não funcionou, continua dando o mesmo erro.

Preciso primeiro fazer a função funcionar corretamente, para depois passa-la para uma DLL.

O erro pode estar bem ´na cara´, mas eu não consigo ver.

Tem como eu enviar esse Projeto para vocês testarem?

Abraços

Aguardo...


Responder

Gostei + 0

25/11/2007

Cps.art

Olá amigos.

Já descobri o erro.
Uma operação da função estava errada.
Acertei e consegui criar a DLL e funcionou, retorna ´V´ ou ´F´ como eu queria, só tem um problema, agora quando fecho o Aplicativo que busca a função, executado atraves do RUN do Delphi, dá esse erro.

[b:8c5edf3d2d]Project Project1.exe raised exception class EInvalidPointer with message ´Invalid pointer operation´.[/b:8c5edf3d2d]

Quando executo o projeto já compilado (.EXE) da esse erro abaixo:

[b:8c5edf3d2d]Exceção exceção de software desconhecida (0x0eedfade) em 0x7c812a5b.[/b:8c5edf3d2d]

Ou seja, é o mesmo erro, só as mensagens é que são, a primeira do Delphi e a segunda do Windows.

Falta alguma coisinha mais.

Espero alguma dica.

Obrigado.


Responder

Gostei + 0

25/11/2007

Werlon Goulart

Tem q ver como ficou a funcão...

Grande abraço
Werlon Goulart


Responder

Gostei + 0

25/11/2007

Massuda

[quote:d16ffd34c2=´Werlon Goulart´]O Sharemem deve ser declarado se forem passados como Retorno Strings Longas ou Arrays da DLL para o Chamador.[/quote:d16ffd34c2]Eu sempre respeitei esse aviso lá no início da DLL...
if your DLL exports any procedures or functions that pass strings as parameters or function results.
...ou seja, usar ShareMem sempre que usar string como parametro ou retorno.


Responder

Gostei + 0

26/11/2007

Cps.art

E quanto ao erro que está dando agora, que descrevi na minha ultima postagem acima, podem me dar uma luz?

[b:b4532cf167]Project Project1.exe raised exception class EInvalidPointer with message ´Invalid pointer operation´[/b:b4532cf167]

Coloquei o ShareMem na função e no DPR do projeto.

Agradeço.


Responder

Gostei + 0

26/11/2007

Massuda

O mais simples é você voltar para o código que você postou inicialmente e ver porque o StrToInt está dando a exceção EConvertError...


Responder

Gostei + 0

26/11/2007

Cps.art

Pois é Massuda, o erro de conversào que estava acontecendo eu consertei.
A função está funcionando perfeitamente, e o erro que está ocorrendo agora é quando eu fecho o aplicativo.

[b:0c35cbd0b4]Project Project1.exe raised exception class EInvalidPointer with message ´Invalid pointer operation´ [/b:0c35cbd0b4]

Sabe algo sobre isso?


Responder

Gostei + 0

27/11/2007

Cps.art

Resolvido o problema.

Eu tinha colocado o ShareMem no Uses no DPR do aplicativo, só que não estava na primeira linha.

Coloquei o ShareMem na primeira linha do Uses do DPR e na primeira linha do Uses da Unit da Função e parou de dar o problema.

Obrigado por enquanto, vou precisar de vocês ainda.

Abraços.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar