Einzelnen Beitrag anzeigen

Thomas233

Registriert seit: 20. Feb 2004
Ort: Villach
66 Beiträge
 
Delphi 2005 Personal
 
#1

Funktionspointerübergabe eines C-Programmes an Delphi-DLL

  Alt 10. Mär 2006, 16:56
Hi,

ich habe ein ganz spezielles Problem an dem sowohl C++ sowie Delphi (und d.h. auch teilweise die WinApi) beteiligt ist.

Zuerst einmal die Problemstellung:
Von einem C-Programm aus rufe ich eine von mir mit Delphi erstellte Dll auf.
Das funktioniert soweit ganz gut, aber in der Dll gibt es eine Funktion die auf ein Ereignis reagieren soll und dann dieses Ereignis an eine Funktion im C-Programm weitergeben soll (Callback).
Das ganze mache ich derzeit so das ich der Dll über eine Funktion einen Funktionspointer übergebe welche die Dll dann im Ernstfall aufrufen soll (im C-Programm).

Leider klappt das nicht da ich so immer eine Zugriffsverletzung kriege.

Ich denke mal das Problem ist die Übergabe des Funktionspointers, kann aber natürlich auch woanders liegen (es lässt sich ja leider nicht so einfach debuggen).

Zur Veranschaulichung hier die wichtigsten Ausschnitte beider Codes (bei dem ganzen handelt es sich übrigens um eine teilweise Auslagerung der VCL in eine Dll):

Delphi-Quellcode:
//Delphi Code
//DLL

//...

//Konstanten
const VCLA_CLOSE=$aa;
const VCLA_CLICK=$ab;
const VCLA_DBLCLICK=$ac;
const VCLA_CHANGE=$ad;

//Globale Deklarationen
var Controls:TObjectList; //Alle VCL-Controls
var ControlsAliases:TStringlist; //Hier werden die Namen der Controls gespeichert (zur Zuordnung von Ids)
var ctrlsEventCallbackFunc:TList; //Pointer auf die Callback-Funktionen
var EventHandlerInst:TVCLAdaptEventHandler; //Event-Handler, mit den Methoden in dieser Klasse werden die Callback-Funktionen aufgerufen

type StandardEventCallback=procedure(_ctrlname:PChar;action:integer;_value:PChar); stdcall; //Das ist die Deklaration der Callback-Funktion im C-Programm
type pStandardEventCallback=^StandardEventCallback;

function SetCallback(_ctrlname:PChar;var _callbfunc:pStandardEventCallback):integer; stdcall; export; //Hiermit wird so eine Callbackfunktion "registriert"
var tmpid:integer;
begin
Result:=0;

if (ControlsAliases<>nil) and (ctrlsEventCallbackFunc<>nil) then begin
  tmpid:=ctrlsEventCallbackFunc.Add(_callbfunc); //Pointer auf die Callback-Funktion im C-Programm wird in die zugehörige-Liste eingetragen

  ControlsAliases.Add(_ctrlname); //Der Name des zugehörigen Controls wird ebenfalls gespeichert
end
else
  Result:=-1;
end;

function GetEventCallbFuncFromLists(_ctrlname:PChar):pStandardEventCallback; //Findet heraus ob eine Callback-Funktion zum angegebenen Control existiert und liefert den Pointer auf die Callback-Funktion zurück
var tmpid:integer;
begin
if (ControlsAliases<>nil) and (ctrlsEventCallbackFunc<>nil) then begin
  tmpid:=ControlsAliases.IndexOf(_ctrlname); Sucht die Id in der Callback-Pointer-Liste heraus (anhand des Control-Namens)

  if tmpid>-1 then
    Result:=ctrlsEventCallbackFunc[tmpid];
end
else
  Result:=nil;
end;

procedure TVCLAdaptEventHandler.CloseEventHandler(_sender:TObject;var _action:TCloseAction);
var tmpCallbFunc:pStandardEventCallback; //Diese Funktion springt bei Bedarf in die Callback-Funktion im C-Programm
begin
tmpCallbFunc:=GetEventCallbFuncFromLists(PChar(TControl(_sender).Name)); //s.o.

if tmpCallbFunc<>nil then //Wenn Callback-Funktion gefunden
  tmpCallbFunc^(PChar(TControl(_sender).Name),VCLA_CLOSE,PChar(nil)); //Aufruf der Callback-Funktion im C-Programm, ich glaube HIER kommt es zum Fehler!
end;

//...
Code:
//C++ Code
//Hauptprogramm (Win32)

//Folgendes steht in einer Header
//...
#define VCLA_CLOSE 0xaa;
#define VCLA_CLICK 0xab;
#define VCLA_DBLCLICK 0xac;
#define VCLA_CHANGE 0xad;

typedef int (__stdcall *VCLADAPTSetCallback)(char*,void*); //Die SetCallback Methode in der Dll

VCLA_SetCallback = (VCLADAPTSetCallback)GetProcAddress(h_VCLA_DLL,"SetCallback"); //Nachdem die Dll geladen wurde wird die SetCallback-Methode ebenfalls geladen (ist nicht NULL !!)

//...

//In Haupt-Cpp-Datei
void __stdcall CALLBACK AppCall(char* _ctrlname,int _action,char* _val) //Dies ist so eine Callback-Funktion die aus der Dll heraus aufgerufen werden sollte
{
         //...
   PostQuitMessage(0);
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

MSG wmsg;

//...

VCLA_SetCallback(test,AppCall);

while(GetMessage(&wmsg,NULL,0,0))
   {
      TranslateMessage(&wmsg);
      DispatchMessage(&wmsg);
   }
   return wmsg.wParam;

//return 0;


//ENDE
So, das ganze ist ein bissle kompliziert, ich hoffe aber das einer von euch vielleicht das Problem findet.

Wäre jedenfalls echt toll !

Vielen Dank im Vorraus,
Thomas
  Mit Zitat antworten Zitat