Como chamar uma DLL escrita em C

Delphi

21/08/2007

Pessoal...

Em primeiro lugar me desculpem se já possuem tópicos aqui no Fórum que falam sobre assunto, mas é que preciso disso com um pouco de urgência.

Eu tenho uma DLL que foi escrita em C++ e preciso chamar essa DLL no meu sistema que esta sendo desenvolvido em Delphi.
Eu tentei fazer a chamada como eu faria se tivesse escrito essa DLL em Delphi mas não estou conseguindo pois está dando erro que não encontra os parâmetros.

Por favor...quem pouder me ajudar ou dar umas dicas eu agradeço.

Att.


Marcos.gandin

Marcos.gandin

Curtidas 0

Respostas

Massuda

Massuda

21/08/2007

Você deve ter declarado em sua unit ´protótipos´ das funções da DLL... experimente fazer assim...
procedure FazMagica(...bla-bla-bla...); cdecl; external ´sua.dll´;



GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Massuda

A minha declaração a DLL está sendo feita da seguinte forma:

function BoxProperties(double L, double H, double W, double& A, double& V); external ´minhaDLL.dll´;


No corpo da DLL escrita em C++, a declaração da função que estou chamando está assim:

extern "C" __declspec(dllexport) void BoxProperties(double Length, double Height,  double Width, double& Area, double& Volume);


O que eu estou fazendo de errado ?


GOSTEI 0
Massuda

Massuda

21/08/2007

Você deveria declarar o ´protótipo´ da função em C++ no Delphi assim...
function BoxProperties(L, H, W: Double; var A, V: Double); external ´minhaDLL.dll´;
...se bem que não lembro se ´double&´ do C++ equivale a ´var X: Double´ do ObjectPascal.


GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Tentei fazer como você me falou, mas ainda está dando erro.

Function needs result type


GOSTEI 0
Massuda

Massuda

21/08/2007

Function needs result type
Tinha esquecido desse detalhe...

Tente assim...
procedure BoxProperties(L, H, W: Double; var A, V: Double); external ´minhaDLL.dll´;



GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Troquei function por procedure, mas quando eu chamo está dando o seguinte erro:

Incompatible types: ´Double´ and ´procedure, untyped pointer or untyped parameter´

:?


GOSTEI 0
Massuda

Massuda

21/08/2007

mas quando eu chamo está dando o seguinte erro:
Mostre como está chamando. Todos os parametros devem ser do tipo Double.

Lembrando que, como é uma procedure, você não pode atribuir o ´retorno da procedure´ a uma variável.


GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Este é o código que estou usando:

procedure TfrmTestaDLL.Button1Click(Sender: TObject);
var
  l, h, w, area, volume, resultado : double;
begin
  l := StrToFloat(edtLength.Text);
  h := StrToFloat(edtHeight.Text);
  w := StrToFloat(edtWidth.Text);
  area := StrToFloat(edtArea.Text);
  volume := StrToFloat(edtVolume.Text);
  resultado := BoxProperties(l, h, w, area, volume);
  ShowMessage(´Valor da Area e do Volume: ´ + FloatToStr(resultado));
end;



GOSTEI 0
Massuda

Massuda

21/08/2007

resultado := BoxProperties(l, h, w, area, volume);
BoxProperties é uma procedure, não retorna valor algum, logo está errado tentar atribuir algum valor a ´resultado´.

ShowMessage(´Valor da Area e do Volume: ´ + FloatToStr(resultado));
BoxProperties aparentemente retorna valores em Area e Volume, conforme a declaração dela em C.


GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Mas e como eu vou fazer pra mostrar esses valores uma vez que eu os mando para a DLL ?


GOSTEI 0
Massuda

Massuda

21/08/2007

Não sei como é essa sua função que está na DLL, mas para mim faz sentido mandar para ela altura, largura e profundidade e receber de volta área e volume.

Acho que você devia apenas mandar os valores L, H e W e mostrar o que retornar em Area e Volume.


GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

O conteudo da DLL está assim:

// win32DLL.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

// This function is used to calculate the total area of a parallelepid rectangle
double BoxArea(double L, double H, double W);

// This function is used to calculate the volume of a parallelepid rectangle
double BoxVolume(double L, double H, double W);

// This function is used to get the dimensions of a rectangular parallelepiped
// calculate the area and volume, then pass the calculated values to the
// function that called it.

extern "C" __declspec(dllexport) void BoxProperties(double Length, double Height,
                   double Width, double& Area, double& Volume);


BOOL APIENTRY DllMain( HANDLE hModule,  
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
 )
{
    return TRUE;
}


double BoxArea(double L, double H, double W)
{
    return 2 * ((L*H) + (L*W) + (H*W));
}

double BoxVolume(double L, double H, double W)
{
    return L * H * W;
}

void BoxProperties(double L, double H, double W, double& A, double& V)
{
    A = BoxArea(L, H, W);
    V = BoxVolume(L, H, W);
}



E o código que eu uso pra chamar é aquele que eu postei agora a pouco.


GOSTEI 0
Massuda

Massuda

21/08/2007

É exatamente o que escrevi no meu post anterior.


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

21/08/2007

Este é o código que estou usando:
procedure TfrmTestaDLL.Button1Click(Sender: TObject);
var
  l, h, w, area, volume, resultado : double;
begin
  l := StrToFloat(edtLength.Text);
  h := StrToFloat(edtHeight.Text);
  w := StrToFloat(edtWidth.Text);
  area := StrToFloat(edtArea.Text);
  volume := StrToFloat(edtVolume.Text);
  resultado := BoxProperties(l, h, w, area, volume);
  ShowMessage(´Valor da Area e do Volume: ´ + FloatToStr(resultado));
end;


é como o Massuda disse: sua função serve para calcular a área e volume, dados altura, largura e profundidade. logo, o correto seria:

procedure TfrmTestaDLL.Button1Click(Sender: TObject);
var
  l, h, w, area, volume: double;
begin
  l := StrToFloat(edtLength.Text);
  h := StrToFloat(edtHeight.Text);
  w := StrToFloat(edtWidth.Text);
  BoxProperties(l, h, w, area, volume);
  ShowMessage(´Os valores são -> Area: ´ + FloatToStr(area) + ´ e Volume: ´+  + FloatToStr(volume));
end;



GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Eu coloquei o código como o emerson.en sugeriu mas ainda assim está dando erro na linha:

ShowMessage(´Os valores são -> Area: ´ + FloatToStr(area) + ´ e Volume: ´+  + FloatToStr(volume));


Operator not applicable to this operand type


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

21/08/2007

foi um pequeno erro na transcrição. não deveria ter dois + em sequencia...

ShowMessage(´Os valores são -> Area: ´ + FloatToStr(area) + ´ e Volume: ´ + FloatToStr(volume));


GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Agora deu certo. O programa compilou, mas quando foi rodar deu o erro;

The application failed to initialize properly (0xc000007b). Click on OK to terminate the application.

Isto está relacionado com a chamada à DLL?


GOSTEI 0
Massuda

Massuda

21/08/2007

Como você gerou essa DLL? Ela é para Win32?


GOSTEI 0
Marcos.gandin

Marcos.gandin

21/08/2007

Massuda

O que aconteceu foi o seguinte: eu to desenvolvendo um sitema e futuramente vou precisar incorporar algumas DLL´s nele, então eu recebi estes arquivos que um cologa meu tinha feito, justamente pra que eu tentase a comunicação do Delphi com uma DLL feita em C++, pois estas DLL´s que receberei serão desenvolvidas em C++.

Então eu tenho 2 arquivos feitos em C++ com os nomes win32DLL.cpp e ConsoleDLL.cpp que geraram os arquivos win32DLL.dll e win32DLL.lib.

Isso tudo eu já recebi pronto e estava tentando fazer com que um programa em Delphi conseguisse se comunicar com essa DLL.


GOSTEI 0
POSTAR