dieses Thema ist ähnlich, wie mein gestriges, denn ich versuche weiterhin, den IO-Warrior 24 mit FreePascal unter Linux anzusprechen. Dabei bin ich möglicherweise auf Probleme mit der Library gestoßen, denn ich habe nach immer wieder auftretendem Absturz und stundenlanger Suche den Fehler eingrenzen können. Ich habe ein Testprogramm geschrieben, das aus folgenden stark reduzierten Units besteht:
Code: Select all
unit iowkit;
interface
const
IOWKIT_VENDOR_ID = $07c0;
IOWKIT_PRODUCT_ID_IOW24 = $1501;
IOWKITDllName = 'libiowkit.so';
type
IOWKIT_HANDLE = Pointer;
function IowKitOpenDevice: IOWKIT_HANDLE; stdcall;
procedure IowKitCloseDevice(devHandle: IOWKIT_HANDLE); stdcall;
function IowKitVersion: PChar; stdcall;
function IowKitGetProductId(devHandle: IOWKIT_HANDLE): Cardinal; stdcall;
function IowKitGetRevision(devHandle: IOWKIT_HANDLE): Cardinal; stdcall;
implementation
function IowKitOpenDevice: IOWKIT_HANDLE; stdcall; external IOWKITDllName name 'IowKitOpenDevice';
procedure IowKitCloseDevice(devHandle: IOWKIT_HANDLE); stdcall; external IOWKITDllName name 'IowKitCloseDevice';
function IowKitVersion: PChar; stdcall; external IOWKITDllName name 'IowKitVersion';
function IowKitGetProductId(devHandle: IOWKIT_HANDLE): Cardinal; stdcall; external IOWKITDllName name 'IowKitGetProductId';
function IowKitGetRevision(devHandle: IOWKIT_HANDLE): Cardinal; stdcall; external IOWKITDllName name 'IowKitGetRevision';
end.
Code: Select all
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
SysUtils, Forms, Dialogs, StdCtrls, iowkit, Classes;
type
{ TForm1 }
TForm1 = class(TForm)
Button3: TButton;
procedure Button3Click(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure test1();
var
ioHandle: IOWKIT_HANDLE = nil;
begin
ShowMessage ('Bibliothek Version: ' + IowKitVersion);
ioHandle := IowKitOpenDevice();
if Assigned(ioHandle) then begin
if (IowKitGetProductId(ioHandle) = IOWKIT_PRODUCT_ID_IOW24) then begin
ShowMessage ('Es wurde ein IO-Warrior 24 gefunden!');
end;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
test1();
end;
end.
Und jetzt wird es kurios: wenn ich die Zeile ...
if (IowKitGetProductId(ioHandle) = IOWKIT_PRODUCT_ID_IOW24) then begin
durch diese Zeile ersetze ...
if (IntToStr(IowKitGetProductId(ioHandle)) + ' ' = IntToStr(IOWKIT_PRODUCT_ID_IOW24) + ' ') then begin
... dann funktioniert es. Sprich, ich vergleiche nicht den Rückgabewert von IowKitGetProductId mit IOWKIT_PRODUCT_ID_IOW24, sondern wandle die Werte in einen String um und hänge ein Leerzeichen an.
Dieses Leerzeichen ist wichtig, denn wenn ich mir in oberem Beispiel statt der if-Abfrage die Kit-Revision anzeigen lassen möchte, führt der Befehl ...
ShowMessage (IntToStr(IowKitGetrevision(ioHandle)));
... zu einem Absturz, wogegen der Befehl ...
ShowMessage (IntToStr(IowKitGetrevision(ioHandle)) + ' ');
... erfolgreich ist - wieder macht das Leerzeichen am Ende den Unterschied!
Das Problem habe ich übrigens nur mit den Befehlen "IowKitGetProductId" und "IowKitGetRevision" feststellen können, alle anderen Befehle funktionieren tadellos. Wenn ich diese Befehle nicht verwende, kann ich unter Linux genauso auf den IO-Warrior 24 zugreifen wie unter Windows und erfolgreich Daten auslesen.
Es fällt auf, daß die beiden Befehle einen Rückgabewert vom Typ "Cardinal" haben. Aber egal ob ich den Wert direkt weiterverwende (und z.B. mit IOWKIT_PRODUCT_ID_IOW24 vergleiche) oder mit IntToStr umwandle, das Ding stürzt ab, außer ich hänge noch ein beliebiges Zeichen an. Da liegt ja die Vermutung nahe, daß da ein String nicht korrekt terminiert sein könnte, aber da der String ja von IntToStr (Systemroutine) aus Cardinal erzeugt wird, sollte die Terminierung ja passen, da sie vom System erledigt wird????
Und ich habe soeben festgestellt, daß der Absturz nur kommt, wenn ich in einer Prozedur als letzten Library-Befehl eine Variante ohne Leerzeichen am Ende ausführe. Folgendes Programm stürzt ab:
Code: Select all
ShowMessage ('Bibliothek Version: ' + IowKitVersion);
ioHandle := IowKitOpenDevice();
if Assigned(ioHandle) then begin
ShowMessage (IntToStr(IowKitGetrevision(ioHandle))+' ');
ShowMessage (IntToStr(IowKitGetrevision(ioHandle)));
end;
Code: Select all
ShowMessage ('Bibliothek Version: ' + IowKitVersion);
ioHandle := IowKitOpenDevice();
if Assigned(ioHandle) then begin
ShowMessage (IntToStr(IowKitGetrevision(ioHandle)));
ShowMessage (IntToStr(IowKitGetrevision(ioHandle))+' ');
end;
Ach ja: es ist Debian 10, 32 Bit, Lazarus 2.0.0+dfsg-2 mit der FPC-Version 3.0.4.
LG Christian