Beschäftige mich jetzt seit einigen Tagen jetzt mit dem SDK und hab mittlerweile auch schon einige Erfolgserlebnisse hinter mir.
Bin jetzt allerdings aber auf einen Fehler gestoßen, den ich nicht in den Griff bekomme: Access Violation – mein absoluter lieblings Fehler in Delphi…
Konnte in mittlerweile auch Example Module vom Kollegen Tommi reproduzieren (besten Dank an dieser Stelle gleich mal für das Beispiel, hat mir einen relativ leichten Einstieg in die Module Erstellung ermöglicht).
Konkret geht es um das Setzen und Auslesen von String Variablen, kann den Fehler mit folgendem Code reproduzieren:
FastMM4 hab ich in den Uses drinnen (hab mir eine Version aus dem Internet geladen und den SourceCode zum SDK gelegt, selbiges für gnugettext.). - gibts da bestimmte Versionen die man verwenden sollte ?
SourceCode sieht im wesentlichen so aus:
function TIPSDevice.getLine:string;stdcall;
begin
LogMessage(KL_DEBUG,'GetLine entered...');
SendData('getLine','entered');
result:=lastLine;
SendData('getLine','Finshed, Result:'+result);
end;
function TIPSDevice.setLine(Text:string):integer;stdcall;
begin
LogMessage(KL_DEBUG,'SetLine entered...');
senddata('setLine','entered');
handleData('PHP',Text);
Result:=length(Text);
end;
procedure TIPSDevice.HandleData(From,Text:string);
var s:string;
begin
LogMessage(KL_DEBUG,'Handle Data entered');
senddata('HandleData','entered');
s:=from+' -->'+Text;
lastline:=s;
logme(s);
DoEcho(Text);
fKernel.VariableManager.WriteVariableString(GetStatusVariableID('LastLineVariable'), s);
senddata('HandleData','finished');
end;
Werd mein eigenes Projekt heute abend nochmals etwas abspecken und auf das wesentliche reduzieren.
Eventuell hab ich auch wirklich nur eine falsche Version von FastMM4 - hatte gar nicht mehr daran gedacht, dass ich mir da eine Version aus dem Netz gesaugt hatte …
Debugger habe ich noch nicht geschafft mit der IPS.exe zum Laufen zu bringen .
Konnte den Fehler trotzdem eingrenzen:
procedure TIPSDevice.HandleData(From,Text:string);
var s:string;
begin
s:=from+' -->'+Text;
fKernel.VariableManager.WriteVariableString(
GetStatusVariableID('LastLineVariable'), s);
end;
der Fehler passiert in der Zeile: s:=from+’ -->’+Text;
wenn man aber die Zeile danach mit dem VariableManager auskommentiert funktionierts wieder - hab keine Idee wie es zu so einem Phänomen kommen kann ???
so, bin jetzt wieder einen Schritt weiter, Debugger läuft, allerdings kann ich mit dem Debugger die AV in Tommis Sample Project nicht reproduzieren.
Reproduzieren kann ich bei meinem eigenen Projekt eine AV im Konstruktor,
sobald ich mit der Maus auf „fKernel.VariableManager“ steht „Auswerten“ und ab diesen Zeitpunkt geht nichts mehr (abgesehen von einem Programmabbruch).
@parsey
Welche Version von FastMM4 bzw. gnugettext it zu empfehlen (Link für Download)?
Das DemoProjekt kompiliert ohne Probleme, benötige jetzt auch meine FastMM4 Version nicht mehr.
habe jetzt folgenden Code in das Demo-Projekt eingefügt:
procedure TIPSTestModule.TestFunction; stdcall;
var
i:integer;
msg:string;
begin
for I := 0 to 99 do
begin
senddata('TestFunction', 'Prepare String, Idx='+IntToStr(i));
msg := msg + '1234567890';
senddata('TestFunction', 'Write Variable, Idx='+IntToStr(i));
fKernel.VariableManager.WriteVariableString(
GetStatusVariableID('TestVariable'), msg);
end;
end;
beim Ausführen der Funktion
<?
TM_TestFunction(33414);
?>
bekomme ich dann beim 10. Durchlauf der Schleife eine AV !!!
Kann das mal wer verifizieren - bin ich wirklich das einzige arme Schwein, der diese AV bekommt …
Schau doch mal nach, dass in den Compileroptionen „HugeStrings“ aktiviert ist. Sonst kann ein String nur 255Bytes aufnehmen. 100x10Byte sind aber schon 1000. Ich weiss jetzt nicht, was im SDK intern beim Variablenmanager verwendet wird, evtl. gibt es dort auch noch ein Limit .
bin jetzt schön langsam mit meinem Latein am Ende, sobald ich fKernel.VariableManager etwas exzessiver benütze, laufe ich in eine AV hinein:
Zwei Fragen:
1.) Kannst Du ausschließen, dass es sich hierbei um einen Bug im SDK handelt.
2.) Was könnte ich sonst noch versuchen (TurboDelphi habe ich noch nicht versucht, kann mir aber nicht vorstellen, dass das was ändert).
Wollte mir eigentlich einen kleinen Logger mit WebFront Interface basteln, aber unter den Voraussetztungen muss ich mein Projektchen wohl „kübeln“.
Hier noch die Sourcen, ansonsten alles gleich wie im Demo Projekt:
interface
uses Windows, Messages, SysUtils, ActiveX, Classes, Forms, StdCtrls,
Dialogs, StrUtils, ExtCtrls, ScktComp, WinSock,
UIPSTypes, UIPSModuleTypes, UIPSDataTypes;
type
IIPSTestModule = interface(IInvokable) ['{C503D47C-32B0-442B-A945-D1D7EBBF6621}']
procedure TestFunction; stdcall;
end;
TIPSTestModule = class(TIPSModuleObject,
IIPSModule,
IIPSTestModule
)
private
public
constructor Create(IKernel: IIPSKernel; InstanceID: TInstanceID); override;
destructor Destroy; override;
procedure LoadSettings(); override;
procedure SaveSettings(); override;
procedure ResetChanges(); override;
procedure ApplyChanges(); override;
procedure TestFunction; stdcall;
class function GetModuleID(): TStrGUID; override;
class function GetModuleType(): TIPSModuleType; override;
class function GetModuleName(): String; override;
end;
implementation
//------------------------------------------------------------------------------
class function TIPSTestModule.GetModuleID(): TStrGUID;
begin
Result := GUIDToString(IIPSTestModule); //Will return Interface GUID
end;
//------------------------------------------------------------------------------
class function TIPSTestModule.GetModuleType(): TIPSModuleType;
begin
Result := mtDevice;
end;
//------------------------------------------------------------------------------
class function TIPSTestModule.GetModuleName(): String;
begin
Result := 'TestModule';
end;
//------------------------------------------------------------------------------
constructor TIPSTestModule.Create(IKernel: IIPSKernel; InstanceID: TInstanceID);
begin
inherited;
RegisterVariable('TestVariable', 'TestVariable', vtString, '');
ConstructorPostProcess;
end;
//------------------------------------------------------------------------------
destructor TIPSTestModule.Destroy;
begin
DestructorPreProcess;
inherited;
end;
//------------------------------------------------------------------------------
procedure TIPSTestModule.LoadSettings();
begin
inherited;
end;
//------------------------------------------------------------------------------
procedure TIPSTestModule.SaveSettings();
begin
inherited;
end;
//------------------------------------------------------------------------------
procedure TIPSTestModule.ResetChanges();
begin
inherited;
end;
//------------------------------------------------------------------------------
procedure TIPSTestModule.ApplyChanges();
begin
inherited;
end;
//------------------------------------------------------------------------------
procedure TIPSTestModule.TestFunction; stdcall;
var
i:integer;
msg:string;
begin
for i := 0 to 20 do
begin
senddata('TestFunction', 'Prepare String, Idx='+IntToStr(i));
msg := msg + '1234567890';
senddata('TestFunction', 'Write Variable, Idx='+IntToStr(i));
fKernel.VariableManager.WriteVariableString(GetStatusVariableID('TestVariable'), msg);
end;
end;
end.
OK, besten Dank, gibt mehr jedenfalls mal die Gewissheit, dass es an meiner Delphi Version liegen muss (hab mittlerweile auch schon das Betriebssystem gewechselt - Win7 auf XP).
habe include von FastMM4 enfernt (sollte ja bei meiner Delphi Version dabei sein), Pfad für SDK angepasst, compile (meine DLL ist etwas grösser), in IPS kopiert …
Deine DLL funktioniert problemlos, sobald ich meine kompilierte Version verwende fliege ich nach dem 4. Aufruf der Funktion SetLine auf die „Fresse“ .
CodeGear™ Delphi® 2007 für Win32® Version 11.0.2804.9245