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