Event-Übergabe an C Sharp mittels DLL
Event-Übergabe an C Sharp mittels DLL
Hallo und guten Tag,
gleich vorab, bin neu hier und auch nur Hobby-Programmierer.
Ich nutze Lazarus 2.0.0 (2019-02-03) FPC-Version 3.0.4
Ich habe erfolgreich ein kleines Programm am Laufen, mit welchem ich über die freie Bibliothek 5dPO (SdpoSerial) eine serielle Schnittstelle auslese und diese kontinuierlich reinlaufenden Daten in z.B. ein Stringlist schreibe.
Procedure TFormSettings.ProcessInputDataBahn1(RX:String);
begin
myListe.Add(RX);
end;
procedure TFormSettings.SdpoSerial1RxData(Sender: TObject);
begin
ProcessInputData(SdpoSerial1.SynSer.RecvString(50));
end;
Das funktioniert in einer abgeschlossenen Lazarus-Form.
Jetzt habe ich in C Sharp 2019 ebenfalls ein Programm am Laufen, mit welchem ich eine Serielle Schnittstelle auslesen möchte.
Mit den in C# verfügbaren Möglichkeiten, das Auslesen zu Konfigurieren, komme ich aber nicht zum gleichen guten Ergebnis, wie in Lazarus.
Deshalb möchte ich die Funktion in Lazarus nutzen und dieses als DLL in C# einbinden.
Grundsätzlich habe ich schon eine in Lazarus erstellte DLL in C# erfolgreich eingebunden.
Aber eben nicht mit einem event sondern nur mit fester Parameterübergabe.
Für die Eventübernahme fehlt mir das Programmierwissen.
Wie kann ich das programmieren und SdpoSerial1RxData als event senden/empfangen? Kann mir da jemand helfen?
Besten Dank vorab, Jürgen
gleich vorab, bin neu hier und auch nur Hobby-Programmierer.
Ich nutze Lazarus 2.0.0 (2019-02-03) FPC-Version 3.0.4
Ich habe erfolgreich ein kleines Programm am Laufen, mit welchem ich über die freie Bibliothek 5dPO (SdpoSerial) eine serielle Schnittstelle auslese und diese kontinuierlich reinlaufenden Daten in z.B. ein Stringlist schreibe.
Procedure TFormSettings.ProcessInputDataBahn1(RX:String);
begin
myListe.Add(RX);
end;
procedure TFormSettings.SdpoSerial1RxData(Sender: TObject);
begin
ProcessInputData(SdpoSerial1.SynSer.RecvString(50));
end;
Das funktioniert in einer abgeschlossenen Lazarus-Form.
Jetzt habe ich in C Sharp 2019 ebenfalls ein Programm am Laufen, mit welchem ich eine Serielle Schnittstelle auslesen möchte.
Mit den in C# verfügbaren Möglichkeiten, das Auslesen zu Konfigurieren, komme ich aber nicht zum gleichen guten Ergebnis, wie in Lazarus.
Deshalb möchte ich die Funktion in Lazarus nutzen und dieses als DLL in C# einbinden.
Grundsätzlich habe ich schon eine in Lazarus erstellte DLL in C# erfolgreich eingebunden.
Aber eben nicht mit einem event sondern nur mit fester Parameterübergabe.
Für die Eventübernahme fehlt mir das Programmierwissen.
Wie kann ich das programmieren und SdpoSerial1RxData als event senden/empfangen? Kann mir da jemand helfen?
Besten Dank vorab, Jürgen
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1650
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Event-Übergabe an C Sharp mittels DLL
Das lässt sich über eine Callback Routine lösen.
Aus dem C# Programm kann nun die Procedure doRead aufgerufen werden.
Code: Alles auswählen
// def.inc
type
TMyCallback = procedure(x : char); stdcall;
//dll
{$i def.inc}
procedure doRead(cb : TMyCallback);
var c : char;
begin
c := doReadSerial;
cb(c);
end;
exports doRead;
Re: Event-Übergabe an C Sharp mittels DLL
Irgenwas mache ich falsch bzw. habe ich nicht verstanden.
Bekomme in C# folgende Meldung:
"Der als Zeichenfolge übergebene Zeiger, darf sich nicht im unteren 64 KB-Speicher des Adressbereichs für den Prozess befinden"
Hier mein Code in Lazarus:
Und das habe ich in C#:
Jürgen
Bekomme in C# folgende Meldung:
"Der als Zeichenfolge übergebene Zeiger, darf sich nicht im unteren 64 KB-Speicher des Adressbereichs für den Prozess befinden"
Hier mein Code in Lazarus:
Code: Alles auswählen
type
TMyCallback = Procedure(cRx: String); stdcall;
function SdpoSerialRxData(): string;
begin
Result := oComPort.SynSer.RecvString(50);
end;
procedure RxString(cRX: TMyCallBack);
var c: String;
begin
c := SdpoSerialRxData();
cRx(c);
END;
exports RxString;
Und das habe ich in C#:
Code: Alles auswählen
public delegate bool FPtr(string value);
[DllImport(".\\lib\\SeriellDLL.dll", EntryPoint = "RxString", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static string RxString(FPtr cb);
private void Button1_Click(object sender, EventArgs e)
{
FPtr cb = new FPtr(DoSomething);
RxString(cb);
}
public bool DoSomething(string value)
{
listBox1.Items.Add(value);
return true;
}
Zuletzt geändert von m.fuchs am Mi 3. Apr 2024, 14:18, insgesamt 1-mal geändert.
Grund: Highlighter hinzugefügt
Grund: Highlighter hinzugefügt
Re: Event-Übergabe an C Sharp mittels DLL
Dein Beispiel kapiere ich nicht so ganz.fliegermichl hat geschrieben: Mi 3. Apr 2024, 12:05 Das lässt sich über eine Callback Routine lösen.
Wofür brauchst du hier überhaupt ein Callback? Mann kann ja c (wieso eig. char?) direkt zurückgeben.
Sinnvoller wäre doch, erst eine Callbackfunktion global zu registrieren um sie dann bei Bedarf aufzurufen und nicht in der von aussen aufgerufenen Funktion.
Oder sehe ich das falsch?
@jlazarus: Ich habe wirklich nicht viel Ahnung von CSharp, aber String als Parametertyp geht wahrscheinlich nicht.
Nimm PChar.
Re: Event-Übergabe an C Sharp mittels DLL
@theo
Hab PChar probiert.
Ist aber dasselbe Ergebnis.
Klappt leider nicht.
Hab PChar probiert.
Ist aber dasselbe Ergebnis.
Klappt leider nicht.
Re: Event-Übergabe an C Sharp mittels DLL
Wie gesagt, von C# habe ich kaum Ahnung, aber..
public extern static string RxString(FPtr cb);
..schaut schon mal suspekt aus. Eine Procedure hat keinen Rückgabewert (hier string)
public extern static string RxString(FPtr cb);
..schaut schon mal suspekt aus. Eine Procedure hat keinen Rückgabewert (hier string)
Re: Event-Übergabe an C Sharp mittels DLL
Du hast recht.
Habs geändert in:
public extern static void RxString(FPtr cb);
Jetzt empfange ich zumindest EIN Datenpaket.
Die Schnittstelle empfängt aber fortlaufend Daten.
Die kommen nicht rein.
Ich hab leider keine Ahnung, ob das Problem auf Lazarus- oder C#-Seite liegt.
Habs geändert in:
public extern static void RxString(FPtr cb);
Jetzt empfange ich zumindest EIN Datenpaket.
Die Schnittstelle empfängt aber fortlaufend Daten.
Die kommen nicht rein.
Ich hab leider keine Ahnung, ob das Problem auf Lazarus- oder C#-Seite liegt.
Re: Event-Übergabe an C Sharp mittels DLL
Willst du nicht lieber Synapse Synaser verwenden?
https://wiki.freepascal.org/Hardware_Ac ... munication
http://synapse.ararat.cz/doc/help/synas ... erial.html
Soweit ich sehe, ist SdpoSerial GUI-/Ereignisorientiert und das passt für eine DLL sowieso nicht.
https://wiki.freepascal.org/Hardware_Ac ... munication
http://synapse.ararat.cz/doc/help/synas ... erial.html
Soweit ich sehe, ist SdpoSerial GUI-/Ereignisorientiert und das passt für eine DLL sowieso nicht.
Re: Event-Übergabe an C Sharp mittels DLL
Hallo theo.
Im Moment komme ich leider nicht dazu, Synapse Synaser auszuprobieren.
Es ist aber auch so, dass ich 5Dpo SdpoSerial schon eine ganze Weile mit Lazarus im Einsatz habe und genau das Ergebnis habe, dass ich brauche.
Ich glaube sogar, dass ich damals Synaser probiert habe, aber damit nicht so zufrieden war.
Ich suche also erstmal weiter nach einer Lösung, SdpoSerial aus Lazarus mit C# zu verbinden.
Jürgen
Im Moment komme ich leider nicht dazu, Synapse Synaser auszuprobieren.
Es ist aber auch so, dass ich 5Dpo SdpoSerial schon eine ganze Weile mit Lazarus im Einsatz habe und genau das Ergebnis habe, dass ich brauche.
Ich glaube sogar, dass ich damals Synaser probiert habe, aber damit nicht so zufrieden war.
Ich suche also erstmal weiter nach einer Lösung, SdpoSerial aus Lazarus mit C# zu verbinden.
Jürgen
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1650
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Event-Übergabe an C Sharp mittels DLL
Mein Beispiel war etwas unglücklich.
Die Idee war, daß die Routine in der DLL solange läuft, bis eine Abbruchbedingung eintritt.
In der Zwischenzeit sendet sie jedes empfangene Byte bzw. Char an die Callback Routine.
Die Idee war, daß die Routine in der DLL solange läuft, bis eine Abbruchbedingung eintritt.
In der Zwischenzeit sendet sie jedes empfangene Byte bzw. Char an die Callback Routine.
Re: Event-Übergabe an C Sharp mittels DLL
Ich sehe im ReadMe von SdpoSerial folgendes:theo hat geschrieben: Do 4. Apr 2024, 10:47 Willst du nicht lieber Synapse Synaser verwenden?
https://wiki.freepascal.org/Hardware_Ac ... munication
http://synapse.ararat.cz/doc/help/synas ... erial.html
Soweit ich sehe, ist SdpoSerial GUI-/Ereignisorientiert und das passt für eine DLL sowieso nicht.
"TSdpoSerial allows asynchronous communication using a serial port based on Synaser. Works in Linux and Windows."
Letztendlich ist es so, dass oComPort.SynSer.RecvString(50) fortlaufend StringPakete bis zum Timout 50 empfängt.
Und diese Pakete möchte ich fortlaufend ausgeben und in C# empfangen.
Mit einem Paket klappt es ja, aber fortlaufend eben nicht.
Aus meiner Sicht macht das reine Synaser auch nichts anderes.
Re: Event-Übergabe an C Sharp mittels DLL
Genau. Und deshalb sollte es mit Synaser alleine auch gehen, ohne die für eine DLL unnötigen bis störenden GUI Abhängigkeiten.jlazarus hat geschrieben: Fr 5. Apr 2024, 10:37 Ich sehe im ReadMe von SdpoSerial folgendes:
"TSdpoSerial allows asynchronous communication using a serial port based on Synaser. Works in Linux and Windows."
Das funktioniert nicht so, kann man in der Synaser Doku nachlesen. Der wartet im Prinzip "timeout" lang auf ein CRLF und gibt dann den String davor zurück.jlazarus hat geschrieben: Fr 5. Apr 2024, 10:37 Letztendlich ist es so, dass oComPort.SynSer.RecvString(50) fortlaufend StringPakete bis zum Timout 50 empfängt.
http://synapse.ararat.cz/doc/help/synas ... Recvstring
Du musst sowieso in einen Loop gehen.
https://wiki.freepascal.org/Hardware_Access#Synaser
Aber ganz ehrlich, ich würde versuchen das in C# zu lösen, wenn du das schon verwenden willst. Das ist doch Krampf, dafür extra eine DLL zu basteln.
Re: Event-Übergabe an C Sharp mittels DLL
Ich arbeite bei Seriellen Port gerne mit Synaser
zu beachten ist die Art der Verbindung - Nur Rx, Tx und Gnd, oder auch Steuersignale:
abholen der Bytes
der LastError ändert sich, wenn kein byte in buffer ist.
Ich arbeite mit Bytes, und werf alles in ein TBytes, was ich benötige.
Wenn dann das abschließende kommt, kann das TBytes in einen String umbegoben werden.
Bsp:
kannst auch den Char aus den Bytes direkt machen und an einen string anhängen, gibt viele möglichkeiten, ist nur wichtig, dass in ByteReceived Byte für Byte eingeworfen wird, bis der Buffer leer ist, oder ein anderer Error auf TBlockSerial aufkommt. Daher sind die Steuerzeichen der spec für dich das ausschlaggebende, zum übergeben und anschließendem leeren des Buffers.
Das ist eine kleine Hilfestellung aus dem grauen heraus.
Ich kann dir sagen, dass es in C# genauso funktioniert, da kenne ich aber keine Components, oder ähnliches.
zu beachten ist die Art der Verbindung - Nur Rx, Tx und Gnd, oder auch Steuersignale:
Code: Alles auswählen
SerPort: TBlockSerial;
--- //spontan
SerPort.CTS
SerPort.DSR
SerPort.RING
SerPort.CARRIER
der LastError ändert sich, wenn kein byte in buffer ist.
Code: Alles auswählen
if SerPort.WaitingData > 0 then
begin
ByteReceived(SerPort.RecvByte(0));
while SerPort.LastError = 0 do
ByteReceived(SerPort.RecvByte(0));
end;
Wenn dann das abschließende kommt, kann das TBytes in einen String umbegoben werden.
Bsp:
Code: Alles auswählen
TEncoding.Ansi.GetAnsiString(RxBytes)
Das ist eine kleine Hilfestellung aus dem grauen heraus.
Ich kann dir sagen, dass es in C# genauso funktioniert, da kenne ich aber keine Components, oder ähnliches.
Re: Event-Übergabe an C Sharp mittels DLL
Ich komme momentan nur sporadisch mal zum Thema zurück,
aber eine Frage drängt sich mir auf.
Ist es nicht eigentlich egal, ob ich einen kompletten String einsammle oder die Bytes nachträglich zusammensetzte.
Das war doch nicht mein Ursprungsproblem.
Mir geht es darum, auf diese Ereignisse über die DLL in C# zu reagieren.
In C# habe ich bisher keine Komponente gefunden, die das gleiche Ergebnis der Schnittstellendaten zurück gibt.
In Synaser, oder eben SdpoSerial kann ich besser konfigurieren und es kommt ein jahrelang erprobtes Ergebnis raus.
Alle Komponenten und Versuche, die ich mit C# bisher unternommen habe, schaffen das nicht.
Deshalb hatte ich die Idee, Lazarus zu nutzen und eine eigene DLL zu bauen.
Ich hoffe immernoch, die Ereignisse durch die DLL schleusen zu können.
Aber wie Anfangs geschrieben, ich bin Hobby-Programmierer und vielleicht wünsche ich mir da was, was nicht machbar ist.
Ein Dankeschön schon mal an Alle, die mir hier helfen wollen und schon geholfen haben.
Jürgen
aber eine Frage drängt sich mir auf.
Ist es nicht eigentlich egal, ob ich einen kompletten String einsammle oder die Bytes nachträglich zusammensetzte.
Das war doch nicht mein Ursprungsproblem.
Mir geht es darum, auf diese Ereignisse über die DLL in C# zu reagieren.
In C# habe ich bisher keine Komponente gefunden, die das gleiche Ergebnis der Schnittstellendaten zurück gibt.
In Synaser, oder eben SdpoSerial kann ich besser konfigurieren und es kommt ein jahrelang erprobtes Ergebnis raus.
Alle Komponenten und Versuche, die ich mit C# bisher unternommen habe, schaffen das nicht.
Deshalb hatte ich die Idee, Lazarus zu nutzen und eine eigene DLL zu bauen.
Ich hoffe immernoch, die Ereignisse durch die DLL schleusen zu können.
Aber wie Anfangs geschrieben, ich bin Hobby-Programmierer und vielleicht wünsche ich mir da was, was nicht machbar ist.
Ein Dankeschön schon mal an Alle, die mir hier helfen wollen und schon geholfen haben.
Jürgen
Re: Event-Übergabe an C Sharp mittels DLL
Auf google gibt man irgend etwas mit serial, port ,class und c# ein (oder alle auf einmal) und hat direkt 4 treffer von MS selbst.
Beispiel ist plausibel, oder die Vervollständigung von MS einfach mal auf das Objekt werfen und schauen was IS dir sonst so bietet.
Edit: es geht also mit MS, hab hier auch kurz eine solution aufgemacht, Beispiel macht was es vorgibt.
Beispiel ist plausibel, oder die Vervollständigung von MS einfach mal auf das Objekt werfen und schauen was IS dir sonst so bietet.
Edit: es geht also mit MS, hab hier auch kurz eine solution aufgemacht, Beispiel macht was es vorgibt.