PDA

View Full Version : [Dll.... fatta in c++(Builder) richiamata in pascal(Delphi)]


ohmimmo
29-10-2006, 13:35
Ciao a tutti, sono uno studente universitario ed ho un piccolo problema nel richiamare le funzioni contenute in una DLL fatta in C++ (CBuilder6) con una applicazione scritta in Pascal (Delphi6).
Di seguito riporto il codice scritto:

#### file StaticLd.h #####################################
#ifndef _STATICLD_H
#define _STATICLD_H

#if defined __DLL__
# define DLL_EXP __declspec(dllexport)
#else
# define DLL_EXP __declspec(dllimport)
#endif

//------------------------------------------------------------------------

extern "C" void DLL_EXP Saluti(HWND);
//------------------------------------------------------------------------

class DLL_EXP NomeClasse
{
public:
NomeClasse(HWND hwnd);
void FaQualcosa(char* text);
void Beep();
private:
HWND hWnd;
};
//------------------------------------------------------------------------
#endif
####################################################
###
###
#### file StaticLd.cpp ####################################
//------------------------------------------------------------------------
#include <condefs.h>
#include <windows.h>
//------------------------------------------------------------------------

#pragma argsused
#include "StaticLd.h"

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{

return 1;
}
//------------------------------------------------------------------------
void DLL_EXP Saluti(HWND hWnd)
{
MessageBox(hWnd, "Saluti da una funzione della DLL!", "Messaggio 1 per Filice",
MB_OK | MB_ICONEXCLAMATION);
}
//------------------------------------------------------------------------
NomeClasse::NomeClasse(HWND hwnd)
{
hWnd=hwnd;
}
//------------------------------------------------------------------------
void NomeClasse::FaQualcosa(char* text)
{
MessageBox(hWnd, text, "Messaggio 2 per Filice",MB_OK);
}
//------------------------------------------------------------------------
void NomeClasse::Beep()
{
MessageBeep(-1);
}
//------------------------------------------------------------------------


Questa libreria chiamata in un'applicazione c++ funziona perfettamente.
Riporto di seguito la Unit chiamante, composta da un Form con due pulsanti:


#### file CallDll_Unit.h ####################################
//------------------------------------------------------------------------
#ifndef CallDll_UnitH
#define CallDll_UnitH
//------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//------------------------------------------------------------------------
#endif
####################################################
###
###
#### file CallDll_Unit.cpp ##################################
//------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "CallDll_Unit.h"
#include "StaticLd.h"
//------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Saluti(Handle);
}
//------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
NomeClasse mc(Application->Handle);
mc.FaQualcosa("Saluti da una funzione di una Classe della DLL!");
mc.Beep();
}
//------------------------------------------------------------------------
//##################################################

Mentre nel modulo in pascal, il compilatore non da nessun messaggio di errore però quando lo eseguo da il messaggio:

" Impossibile trovare il punto di ingresso Saluti della procedura nella libreria di collegamento dinamico PrjStaticLd.dll."

Riporto di seguito la Unit dell'applicazione chiamante in Pascal
(approposito, mi limito a chiamare solo la funzione Saluti(.......)):

#### file CallDllU.pas ####################################
unit CallDllU;

interface

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

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;

var

//-- fatta in CBuilder6 -----------------
procedure Saluti(hWnd : HWND ); external 'PrjStaticLd.dll';
//---------------------------------------

implementation {$R *.dfm}
//##################################################
//------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
Saluti(Handle);
end;

//------------------------------------------------------------------------
//##################################################
end.

So dell'esistenza dei modificatori "cdecl, pascal ecc..." per la compatibilità delle librerie ma non trovo materiale per studiarne il significato.
Spero che qualcuno mi risponderà.... aiutooooooooo!!!!!!!!!

71104
29-10-2006, 13:56
un po' ovunque: quelli del compilatore Microsoft per esempio ovviamente sono documentati su MSDN. te ne riassumo brevemente le caratteristiche:

__stdcall - i parametri vengono messi (PUSH) nello stack da destra a sinistra, il cleanup viene fatto dal chiamato

__cdecl - parametri messi da sinistra a destra, cleanup da parte del chiamante; permette di realizzare funzioni "vararg" (ellissi come ultimo "parametro" nel prototipo), al contrario di __stdcall che non lo permette

__fastcall - utilizza i registri general purpose anziché lo stack per passare i primi parametri; se la funzione ha pochi parametri e non usa variabili locali non sarà necessario creare lo stack frame

poi esistono anche __pascal, __fortran e __syscall, ma sono obsolete percui non le usare.

ohmimmo
30-10-2006, 11:28
un po' ovunque: quelli del compilatore Microsoft per esempio ovviamente sono documentati su MSDN. te ne riassumo brevemente le caratteristiche:

__stdcall - i parametri vengono messi (PUSH) nello stack da destra a sinistra, il cleanup viene fatto dal chiamato

__cdecl - parametri messi da sinistra a destra, cleanup da parte del chiamante; permette di realizzare funzioni "vararg" (ellissi come ultimo "parametro" nel prototipo), al contrario di __stdcall che non lo permette

__fastcall - utilizza i registri general purpose anziché lo stack per passare i primi parametri; se la funzione ha pochi parametri e non usa variabili locali non sarà necessario creare lo stack frame

poi esistono anche __pascal, __fortran e __syscall, ma sono obsolete percui non le usare.

//-------------------------

Per prima cosa grazie per avermi risposto.
Il problema è che sono nuovo nella creazione delle dll e forse anche una stupidagine mi blocca, non riesco a capire perche durante l'esecuzione l'applicazione non trova il punto di ingresso alla funzione nella dll.
Se ti và, potresti guardare il codice? Non è tanto, è solo un esempietto che ho preparato per l'occasione.