Autor |
Beitrag |
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 02:15
Hey,
ich arbeite derzeit für eine AG in der Schule an einer Software zum Ansteuern eines RoboTX Interfaces (Fischertechnik). Diese stellen eine Library zur Verfügung, doch mit einer der Funktionen habe ich so meine Probleme:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| 2.13 EnumComPorts DWORD EnumComPorts (DWORD idx, LPSTR comstr, DWORD maxlen) Liefert einen Eintrag aus der von der Library erstellten statischen Liste der zur Verfügung stehenden COM-Ports. Ein vorheriger Aufruf der Funktion "GetAvailableComPorts()" ist notwendig. Der Eintrag wird als String mit Angabe des COM-Ports und einer Beschreibung der Verwendung, wie sie aus der Windows-Registry zu entnehmen ist, zurückgegeben, z.B.: "COM32 (fischertechnik USB ROBO TX Controller)". Der übergebene Stringbuffer muß entsprechend dimensioniert sein, damit dieser den String mit der Beschreibung aufnehmen kann. Aufruf: DWORD idx - Listenindex innerhalb der Liste der verfügbaren COM-Ports 0 < idx < iComPorts (GetAvailableComPorts()) LPSTR comstr - Stringbuffer zur Aufnahme der COM-Beschreibung DWORD maxLen - max. Länge des Stringbuffers Return: DWORD index - Index des Listeneintrags welcher gelesen wurde (= idx), im Fehlerfall wird der Wert FTLIB_ERR_INVALID_PARAM zurückgegeben |
Das sind bis jetzt meine Ansätze, die wohl ein richtiger Fail sind, weil ich von einem "Stringbuffer" nichts verstehe. Ich habe euch ja alles gegeben, was ich habe, bei mir wirft das eine Zugriffsverletzung aus (was euch bestimmt klar ist) für mich ist das halt logisch
Bei MaxLen habe ich einen mehr oder weniger zufälligen Wert genommen, was aus meiner Dummheit resultiert
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function Init(): DWORD; stdcall; external 'ftMscLib.dll' name 'ftxInitLib'; function ComPorts(mode: Integer): DWORD; stdcall; external 'ftMscLib.dll' name 'GetAvailableComPorts'; function EnumComPorts(idx: DWORD; comstr:String; maxlen: DWORD): DWORD; stdcall; external 'ftMscLib.dll' name 'EnumComPorts';
procedure TForm1.Button1Click(Sender: TObject); var test: String; begin Init(); ShowMessage(IntToStr(ComPorts(1))); EnumComPorts(0,test,64); ShowMessage(test); end; |
Danke schonmal!
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 02:35
Versuch es mal so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| function EnumComPorts(idx: DWORD; comstr:PChar; maxlen: DWORD): DWORD; stdcall; external 'ftMscLib.dll' name 'EnumComPorts';
procedure TForm1.Button1Click(Sender: TObject); const MAX_STRLEN = 1024; var test: String; begin Init(); ShowMessage(IntToStr(ComPorts(1))); SetLength(test, MAX_STRLEN); EnumComPorts(0, PChar(test), Length(test)); SetLength(test, StrLen(PChar(test))); ShowMessage(test); end; |
Beim C-Typ LPSTR bin ich gerade nicht sicher, ob das explizit Ansi ist. Falls ja, besser String in AnsiString und PChar in PAnsiChar ändern.
Für diesen Beitrag haben gedankt: Frolo
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 11:42
Du bist ein Schatz. Aber ich musste PAnsiChar verwenden sonst kamen nur chinesische Schriftzeichen. Ich hab nur kleine Verständnisprobleme, weil ich mich mit den einzelnen Variablentypen noch nicht wirklich auseinander gesetzt habe :/
Delphi-Quelltext 1:
| SetLength(test, MAX_STRLEN); |
1. Wieso wird die Länge von "test" genau auf 1024 Zeichen gesetzt?
2. Warum muss man überhaupt PChar nehmen? Was ist der Unterschied zwischen PChar und String? Bzw PAnsiChar und AnsiString?
Delphi-Quelltext 1:
| SetLength(test, StrLen(PChar(test))); |
3. Verstehe ich leider kaum :/ Die Funktion StrLen ist mir quasi unbekannt. Wäre nett wenn du darauf weiter eingehen könntest
Aber schon einmal vielen dank
EDIT:// Hab Delphi 7 mal testweise installiert und habe ein Problem: Es funktioniert alles: Die Anzahl der ComPorts stimmt und auch die Ausgabe des COM-Ports als String geht, nur bekomme ich nach dem Schließen der letzten Messagebox das:
---------------------------
Benachrichtigung über Debugger-Problem
---------------------------
In Projekt D:\Users\Tobias\Downloads\TXInterface\TXInterface\Test.exe trat ein Problem mit folgender Meldung auf: 'access violation at 0xf6190da2: read of address 0xf6190da2'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK
---------------------------
Ich kann mir das nicht erklären, weil danach ja im Grunde nichts mehr passiert o:
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 12:12
Die 1024 ist willkürlich gesetzt. Zu den unterschiedlichen Typen verweise ich einfach auf den Hersteller, das ist mir zuviel zu Tippen. Bzgl. des Fehlers: bist Du sicher, dass er durch diese Routine ausgelöst wird? Oder kommt er auch, wenn diese gar nicht durchlaufen wird?
Für diesen Beitrag haben gedankt: Frolo
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 12:19
Zu dem Fehler: Erstmal, mit Delphi XE3 kommt der Fehler nicht, beim kompilieren unter Delphi 7 aber schon. Der Fehler wird wohl durch die Funktion "ComPorts" ausgelöst, da der Fehler kommt, wenn alle anderen Zeilen auskommentiert sind. Diese Funktion löst folgenden Fehler aus:
---------------------------
Benachrichtigung über Debugger-Problem
---------------------------
In Projekt D:\Users\Tobias\Downloads\TXInterface\Test.exe trat ein Problem mit folgender Meldung auf: 'privileged instruction at 0x0018f5a0'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK
---------------------------
"ComPorts" und "EnumComPorts" bauen ja aufeinander auf, das bedeutet, dass der 2. Fehler wohl nur ausgelöst wird, weil bei "ComPorts" keine statische Tabelle mit den einzelnen Ports angelegt wurde. Aber was bedeutet denn "privileged instruction"?
Hoffe ihr könnt mir helfen (:
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 12:23
Wie sieht denn die Signatur und ggf. die Beschreibung zu dieser Funktion aus?
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 12:38
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| 2.12 GetAvailableComPorts DWORD GetAvailableComPorts (int selectMode) Funktion ermittelt auf Basis der Informationen aus der Windows-Registry alle zur Verfügung stehenden COM-Ports und liefert die Anzahl der Ports zurück. Intern werden diese Informationen in einer statischen Liste zur weiteren Verwendung verwaltet. Zur Ermittlung und Anzeige der zur Verfügung stehenden COM-Ports muss diese Funktion zuerst aufgerufen werden. Aufruf: int selectMode - Angabe, ob alle COM-Ports gelesen werden oder nur die Ports, die für eine Verbindung zu einem ROBO-TX Controller vorgesehen sind (USB oder Bluetooth) ALL_PORTS 0 alle Ports USB_ONLY 1 nur USB-Schnittstellen BT_ONLY 2 nur Bluetooth-Verbindungen Return: DWORD iComPorts - Anzahl der ermittelten COM-Ports in der internen Liste |
Für mich sieht das ja so aus, als ob da iwelche Zugriffsrechte fehlenm aber es ist doch die selbe DLL :/
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 13:37
Wie ist es denn so?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| const ALL_PORTS = 0; USB_ONLY = 1; BT_ONLY = 2; procedure TForm1.Button1Click(Sender: TObject); const MAX_STRLEN = 1024; var test: AnsiString; i: DWORD; begin Init(); for i := 0 to ComPorts(USB_ONLY) - 1 do begin SetLength(test, MAX_STRLEN); ZeroMemory(@test[1], Length(test)); EnumComPorts(i, PAnsiChar(test), Length(test)); SetLength(test, StrLen(PAnsiChar(test))); ShowMessage(test); end; end; |
Für diesen Beitrag haben gedankt: Frolo
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 15:33
Gleiche Problem sry
---------------------------
Benachrichtigung über Debugger-Problem
---------------------------
In Projekt D:\Users\Tobias\Downloads\TXInterface\Test.exe trat ein Problem mit folgender Meldung auf: 'access violation at 0x00447da7: read of address 0x01af36f3'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK
---------------------------
Und wie gesagt tritt ja schon ein Fehler auf, alleine beim Aufruf von "ComPorts"...
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 16:02
Dann weiß ich leider im Moment auch nicht weiter
[edit] Nur zur Sicherheit: es sind aber beides 32Bit-Anwendungen? [/edit]
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 16:20
Jap sind es o:
Soll ich die DLL mal uppen?
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 17:02
Bist Du sicher, dass Du das darfst? Ich wäre damit vorsichtig.
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 17:22
Nein bin ich nicht, aber hier:
www.fischertechnik.d...loads/Computing.aspx
einfach bei "ROBO TX Controller" das runterladen: "PC Programming ROBO TX Controller Version 1.5 - 3,2 MB" Da ist sowohl die Dokumentation drinnen als auch die DLL Danke schonmal!
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 18:32
So, ich habe das gerade mal unter XE versucht, scheitere aber bereits beim Aufruf von ftxIsLibInit, da kommt FTLIB_ERR_LIB_IS_NOT_INITIALIZED zurück.
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 19:05
Übernehm doch einfach meinen Code:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| unit main;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end;
var Form1: TForm1; test: DWord;
implementation
{$R *.dfm}
function GetVer(): DWORD; stdcall; external 'ftMscLib.dll' name 'ftxGetLibVersion'; function Init(): DWORD; stdcall; external 'ftMscLib.dll' name 'ftxInitLib'; function ComPorts(mode: Integer): DWORD; stdcall; external 'ftMscLib.dll' name 'GetAvailableComPorts'; function EnumComPorts(idx: DWORD; comstr:PAnsiChar; maxlen: DWORD): DWORD; stdcall; external 'ftMscLib.dll' name 'EnumComPorts';
procedure TForm1.Button1Click(Sender: TObject); const MAX_STRLEN = 1024; var test: AnsiString; begin Init(); ShowMessage(IntToStr(ComPorts(1))); SetLength(test, MAX_STRLEN); EnumComPorts(0, PAnsiChar(test), Length(test)); SetLength(test, StrLen(PAnsiChar(test))); ShowMessage(test); end;
end. |
Der läuft unter Delphi XE3 perfekt (ohne diese Fehlermeldung) bei Delphi 7 auch, nur kommt am ende der procedure diese Meldung..
|
|
WasWeißDennIch
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: So 24.02.13 19:36
Prüf doch mal den Rückgabewert von Init(), das ist ja nicht umsonst eine Funktion. Möglicherweise müsste ich auch erst den ganzen Treiberkrams installieren, aber so weit möchte ich nicht gehen.
|
|
Frolo
Beiträge: 48
|
Verfasst: So 24.02.13 19:46
Das versteh ich eh nicht so 100%. Wo sind denn die Konstanten definiert? Ich hab das nämlich nicht gefunden und die Treiber brauchst du für die Funktionen noch nicht erst später
EDIT:// Leute das Problem hat sich geklärt, aber wie ey oO Ich hab einfach mal zum testen den Rückgabewert von Init() in einer Variable gespeichert und jetzt gehts verkehrte Welt o:
Der Fehler taucht bei kleinsten Umstellungen wieder auf, vllt liegt es an dem Typ DWORD?
EDIT2:// Habe die Konstanten gefunden
|
|
Blup
Beiträge: 174
Erhaltene Danke: 43
|
Verfasst: Mo 25.02.13 11:02
Eventuell muss "cdecl" statt "stdcall" angegeben werden.
de.wikipedia.org/wiki/Aufrufkonvention
|
|