Hallo, es geht um die Schreib-Funktion eines FTD232-Bausteins den ich mit einer in Windows-Form Anwendung ansprechen möchte. FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesWritten) Mein C++/CLI Compiler meldet keine Fehler, aber bei Ausführung dieser Funktion kommt eine Fehlermeldung über eine Speicherplatzverletzung hoch. Wahrscheinlich habe ich bei der Deklaration zu dieser Variable (LPVOID lpBuffer) einen Fehler gemacht. Wenn ich diese Funktion in VisualBasic mit den Typen FT_Write(integer, string, integer, integer) laufen lasse funktioniert es. Kann mir jemand mitteilen wie man LPVOID, DWORD und LPDWORD richtig deklariert? Vielen Dank! Bernd
"Speicherplatzverletzung" hört sich nach Hardwareproblem an. Vielleicht meinst du "Speicherschutzverletzung"? Deine Angaben sind etwas dürftig, aber mal ins Blaue: - an der Deklaration wird es kaum liegen, das würde der Compiler anmäkeln - bist du sicher, daß du einen vernünftigen Wert übergibst und nicht etwa NULL oder sowas?
BerndB schrieb: > FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD > lpBytesWritten) > > Mein C++/CLI Compiler meldet keine Fehler, aber bei Ausführung dieser > Funktion kommt eine Fehlermeldung über eine Speicherplatzverletzung > hoch. Dann poste Deinen Code. Wie hast Du die Funktion aufgerufen? Nicht erklären, Code zeigen.
Rufus t. Firefly schrieb: > BerndB schrieb: >> FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD >> lpBytesWritten) >> >> Mein C++/CLI Compiler meldet keine Fehler, aber bei Ausführung dieser >> Funktion kommt eine Fehlermeldung über eine Speicherplatzverletzung >> hoch. > > Dann poste Deinen Code. Wie hast Du die Funktion aufgerufen? Und vor allen Dingen, wie sind die Variablen definiert, die du der Funktion übergibst. Merke: Nicht jeder Pointer in einer Argumentliste bedeutet, dass du eine Pointervariable brauchst. In den meisten Fällen ist der Pointer ein Indiz dafür, dass du ein Array oder eine Struktur anlegen musst, deren Adresse an die Funktion übergeben wird. Letzteres ist insbesondere praktisch immer der Fall, wenn die Funktion ziemlich offensichtlich diese Adresse dazu benutzt um an dieser Stelle im Speicher Werte abzulegen oder von dort zu lesen, so wie in deinem Fall. Deine Aussage > Wahrscheinlich habe ich bei der Deklaration zu dieser > Variable (LPVOID lpBuffer) einen Fehler gemacht. lässt mich genau in diese Richtung vermuten: Du hast eine LPVOID Variable angelegt. Und das war dann genau das Falsche. Was du tun müsstest ist ein Array (von Bytes) anzulegen und dessen Start-Adresse an der Stelle lpBuffer durchzuschleusen.
Also hier die Fehlermeldung nach fehlerfreien Compilieren: Es wurde versucht im geschützten Speicher zu lesen oder zu schreiben. Dies ist häufig ein Hinweis darauf, dass anderer Speicher beschädigt ist. Meine Funktion:
1 | private: System::Void send_DMX(int iChannel){ |
2 | //FT_HANDLE handle; deklariert in public
|
3 | LPVOID *lpBuffer = (char)0; |
4 | DWORD b = 1; //Anzahl der Bytes |
5 | LPDWORD lngBytesWritten = 0; |
6 | //break signal
|
7 | FT_SetBreakOn(handle); |
8 | FT_SetBreakOff(handle); |
9 | //write start code = 0
|
10 | if(FT_Write(handle, lpBuffer, b,lngBytesWritten)==FT_OK) //hier Fehlermeldung |
11 | |
12 | lstLoggerList->Items->Add("FT_Write Startcode erfolgreich ausgeführt!"); |
13 | else
|
14 | lstLoggerList->Items->Add("Fehler bei FT_Write Startcode!"); |
15 | }//end function |
[Edit: Durch Einschließen des Codes in [ c ] / [ / c ] wird das ganze etwas lesbarer. Rufus]
Hallo Rufus, danke für deine Mühe!!! Kannst du mir ein Beispiel zeigen wie ich dieses Array richtig anlege und die Anfangsadresse übergebe?
> LPVOID *lpBuffer = (char)0; [..] > LPDWORD lngBytesWritten = 0; [..] > FT_Write(handle, lpBuffer, b,lngBytesWritten) Kokrrektur: char cBuffer = $blubber; // was willst du eigentlich übertragen? [..] DWORD dBytesWritten = 0; [..] FT_Write(handle, &cBuffer, b, &dBytesWritten) ..noch sinnvolle Werte eintragen, dann sollte es klappern.
1 | LPVOID *lpBuffer = (char)0; |
2 | ...
|
3 | if(FT_Write(handle, lpBuffer, b,lngBytesWritten)==FT_OK) //hier Fehlermeldung |
4 | ...
|
Was hättest du denn hier erwartet?
1 | char Buffer[50] = "Hallo World"; |
2 | DWORD BytesToWrite = strlen( Buffer ); |
3 | DWORD BytesWritten = 0; |
4 | |
5 | FT_Write( handle, Buffer, BytesToWrite, &BytesWritten ); |
Ist doch einfach: Im Array Buffer steht das drinnen, was zu senden ist. Die Funktion will die Startadresse davon haben, also kriegt sie die auch. Nun kann es natürlich sein, dass das Array größer ist, als die die darin enthaltenen Daten. Also will die Funktion auch nich wissen, wieviele Bytes aus diesem Buffer zu übertragen sind. Auch das geben wir ihr mit, im nächsten Argument. Und zu guter letzt möchte die Funktion auch noch die Adresse einer DWORD Variablen haben, in die sie hineinschreibt, wieviele Bytes tatsächlich gesendet werden konnten. Buffer und BytesToWrite gehen in die Funktion hinein. Da es sich bei Buffer um ein Array handelt, wird dieses Argument in Form eines Pointers übergeben. BytesWritten hingegen ist anders. Die Funktion möchte darüber dem Aufrufer etwas mitteilen. Und daher benötigt sie einen Pointer dafür. So quasi: Wo bitte darf ich dir meine Ergüsse hinschreiben? Aha, in deine Variable BytesWritten. Gut dass du mir die Adresse davon gegeben hast, dann kann ich das dann dort in den Speicher schreiben.
Du rufst die Funktion FT_Write auf, sagst ihr aber nicht, was sie schreiben soll, aber wieviel. Und das ist nicht alles. Also: FT_Write(handle, lpBuffer, b,lngBytesWritten) Hier muss lpBuffer auf die Daten zeigen, die Du schreiben willst. b enthält die Anzahl der zu schreibenden Bytes, und in lngBytesWritten steht die Adresse einer Variablen drin, in der die Funktion zurückgibt, wieviele Bytes sie tatsächlich geschrieben hat. Du übergibst aber sowohl für lpBuffer als auch für lngBytesWritten einen NULL-Pointer. Das geht komplett in die Hose. Vermutlich willst Du als "start code" ein Byte mit dem Wert 0 versenden. Also sollte das ganze so aussehen:
1 | private: System::Void send_DMX(int iChannel) |
2 | {
|
3 | BYTE bData; |
4 | |
5 | DWORD dwBytesWritten = 0; |
6 | |
7 | //write start code = 0
|
8 | bData = 0; |
9 | |
10 | if (FT_Write(handle, &bData, sizeof (bData), &dwBytesWritten) == FT_OK) |
11 | {
|
12 | // etc.pp.
|
13 | }
|
Und wenn Du die Kanalnummer iChannel als 16-Bit-Wert versenden willst, sieht der Aufruf so aus:
1 | if (FT_Write(handle, &iChannel, sizeof (iChannel), &dwBytesWritten) == FT_OK) |
2 | {
|
3 | // etc.pp.
|
4 | }
|
Du darfst bei Funktionen nicht einfach nur in die Argumentliste schauen, alle Datentypen die du dort findest als Variablen definieren und dann die Funktion aufrufen! Du musst schon auch ein wenig nachdenken, was denn die Funktion mit dem Argument machen wird, welchen Zweck dieses Argument hat und wie es die Funktion verwenden wird. Dann wird nämlich in den meisten Fällen sofort klar, was es insbesondere mit einem Pointer in der Argumentliste auf sich hat und was man als Aufrufer tun muss um dieses Pointerargument korrekt zu bedienen. Edit: > Ich möchte eine 0 übertragen die als Startbyte des AVR's > interprettiert wird. OK. Das muss daher dann wie aussehen?
Donald E. Knuth 'The art of computer programming' 1972 "Pointers are a step backwards from witch we will never recover" Wie recht er hatte!!
Leider meckert der Compiler weil er BYTE nicht kennt!?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.