PythonNet - EventHandler Operanttypen Fehler

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Guten Morgen allerseits,

Ich möchte von einer DLL einen EventHandler benutzen.
'public EventHandler<IOStatus> IOStatusChanged;'

Code:

Code: Alles auswählen

self.device  = LibCronusMAX.SingleDevice()
self.device.IOStatusChanged += EventHandler[EventArgs](self.IoStatusChanged)
Fehlercode:

Code: Alles auswählen

self.device.IOStatusChanged += EventHandler[EventArgs](self.IoStatusChanged)
TypeError: unsupported operand type(s) for +=: 'NoneType' and '0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'
Die Klasse 'IOStatus' verwendet EventArgs ('public class IOStatus : EventArgs'), wodurch die Instanzen automatisch Werte erhalten, sollten sie selbst keine besitzen (wenn ich das so richtig verstanden habe).
Nur verstehe ich nicht was ich falsch mache. Leider habe ich auch bei Google keinen Ansatz gefunden, womit ich es lösen könnte.

----------
[EDIT]
Entferne ich allerdings den Index bei:
' self.device.IOStatusChanged += EventHandler[EventArgs](self.IoStatusChanged) '

Erhalte ich den Fehler:
' TypeError: unsupported operand type(s) for +=: 'NoneType' and 'EventHandler' '
(https://ironpython.net/documentation/dotnet/dotnet.html)
----------

Grüße,
xXSkyWalkerXx1
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Hmm, wenn laut API 'IOStatusChanged' = 'EventHandler<IOStatus>", dann müsste es doch eher wie folgt aussehen:

Code: Alles auswählen

self.device.IOStatusChanged += self.IoStatusChanged
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Zu dem ganzen Kram kann hier keiner was sagen. Weil die wenigsten IPython benutzen, und von denen dann nochmal noch weniger dein Chronus-Ding. Da bist du der einzige. Mehr als die Fehlermeldung nochmal vorlesen ("Da ist etwas None") kann man da leider nicht machen.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Ja, ich sehe, ich hätte ja auch Mal den Code der C# DLL posten können:

Code: Alles auswählen

// (in Kurzform)
public sealed class SingleDevice : IDisposable{
	public EventHandler<IOStatus> IOStatusChanged;
 	 }
// IOStatus Klasse
public class IOStatus : EventArgs{
	//<code>
	}
Naja, vllt kennt sich einer ja mit IronPython/PythonNet aus und wüsste was zu tun ist.

Im Internet finde ich oft den Code als Lösung:
C# (cs)

Code: Alles auswählen

serialcom2.SerialreceiveEvent += new EventHandler<SerialEventArgs>(Serialrec_SerialrecEvent);
Python

Code: Alles auswählen

yc = YourClass();
yc.Changed += SomeHandler;
Nur bei mir funktioniert es nicht.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Laut https://riptutorial.com/ironpython/exam ... ironpython macht man die Typspezialisierung tatsaechlich mit den [] anstatt der in Python nicht verfuegbaren <>.

Damit muss dein Code aber eher so aussehen:

Code: Alles auswählen

.... +=  EventHandler[IoStatus](...)
Und das sehe ich nicht.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Die Idee kam mir auch schon, erhalte dann aber den Fehler:

Code: Alles auswählen

TypeError: unsupported operand type(s) for +=: 'NoneType' and '0, Culture=neutral, PublicKeyToken=null]]'
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Irgendwas an deinen beteiligten ist halt None, dazu musst du den Ausdruck mal auseinander pulen, und schauen, wer.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Also wenn, dann müsste 'IOStatusChanged' None/null sein:

Code: Alles auswählen

// LibCronusMAX.SingleDevice() - Eventhandler Instanz
public EventHandler<IOStatus> IOStatusChanged;

// LibCronusMax.IOStatus Klassenbezeichnung
public class IOStatus : EventArgs
Ich frage Mal der Weile im Forum von denen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Kannst du das nicht rausfinden? Per print? Das ein solcher Member None ist halte ich im uebrigen fuer recht unwahrscheinlich.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Mit 'print(type(self.device.IOStatusChanged))' gibt er mir doch tatsächlich '<class 'NoneType'>' aus.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

joa. Dann hast du ja ne Hausaufgabe.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Herauszufinden, warum es eine NoneType-Klasse ist oder was? :D
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist etwas sehr umstaendlich ausgedrueckt. Es ist einfach None. Der Event-Handler (wenn ich das richtig sehe) ist also nicht aufgesetzt. Warum nicht ist die Hausaufgabe, ja.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Im Forum von CronusMax steht für C#:

Code: Alles auswählen

LibCronusMAX->IoStatusChanged += gcnew EventHandler<LibCronusMAX::IOStatus^>(this, &MyForm::IoStatusChanged); // Subscribe to input/output changes/updates

void DeviceInfoChanged(System::Object^ sender, LibCronusMAX::IOStatus^ status) {
}
Im Index ist ja ein "^" (XOR) enthalten, heißt das, es müsste in Python "self.device.IOStatusChanged += EventHandler[LibCronusMAX.IOStatus ^ None](self.ioChanged)" heißen?
[EDIT] Obwohl, ne, macht kein Sinn.
Der Event-Handler (wenn ich das richtig sehe) ist also nicht aufgesetzt.
* Ja, EventHandler
* Was meinst du mit "aufgesetzt"? Warum es kein EventHandler ist, obwohl steht, dass 'IOStatusChanged' = 'EventHandler<IOStatus>' ist, aber über Python es als "NoneType" ausgegeben wird?
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@xXSkyWalkerXx1: Da ist kein XOR. Das ``^`` hat an der Stelle eine andere Bedeutung, das ist ein „managed handle“. Das ist auch kein C# sondern C++/CLI also ein C++-Dialekt für .NET.

Da wird das Objekt auf dem ``+=`` ausgeführt wird ja offensichtlich über ein Objekt mit dem Namen `LibCronusMAX` referenziert. Was hat *das* denn für einen Typ? Das ist nämlich IMHO ein komischer Name für ein Objekt vom Typ `SingleDevice`.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

__blackjack__ hat geschrieben: Mittwoch 17. Juni 2020, 14:24 Da ist kein XOR. Das ``^`` hat an der Stelle eine andere Bedeutung, das ist ein „managed handle“. Das ist auch kein C# sondern C++/CLI also ein C++-Dialekt für .NET.
Deswegen sagte ich ja, dass es kein Sinn macht.
Warum ist es kein C#? Die Quelldatein, aus der die CronusMax API stammt, hat nämlich die ".cs" Dateiendung.
__blackjack__ hat geschrieben: Mittwoch 17. Juni 2020, 14:24 Da wird das Objekt auf dem ``+=`` ausgeführt wird ja offensichtlich über ein Objekt mit dem Namen `LibCronusMAX` referenziert. Was hat *das* denn für einen Typ? Das ist nämlich IMHO ein komischer Name für ein Objekt vom Typ `SingleDevice`.
"self.device.IOStatusChanged" (oder exakt: LibCronusMAX.SingleDevice().IOStatusChanged) ist eine "NoneType"-Klasse.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@xXSkyWalkerXx1: Was weiss ich warum das kein C# ist, das musst Du schon den Autor fragen. Und natürlich macht es Sinn. Es ist ja kein XOR und kein Python. Operatoren beziehungweise Zeichen bedeuten ja nicht in allen Programmiersprachen das gleiche. In den meisten BASIC-Dialekten ist ``^`` beispielsweise der Potenzoperator und in Pascal werden damit bei Typen Zeiger deklariert und in Ausdrücken Zeiger dereferenziert. Letzteres scheint C++/CLI von Pascal abgeschaut zu haben um damit zwei verschiedene Zeigertypen unterscheiden zu können: Solche wie in C++ üblich, wo sich der Programmierer um die Speichervewaltung kümmern muss, und solche bei denen das eine automatische Speicherverwaltung tut, also ein „garbage collector“ (GC). Deswegen auch das ``gc`` in ``gcnew``.

Ich meinte was ist das im C++/CLI-Quelltext für ein Typ. Denn steht ja nicht ``LibCronusMAX->SingleDevice()->IOStatusChanged`` sondern ``LibCronusMAX->IOStatusChanged`` und ich würde mich schon arg wundern wenn `LibCronusMAX` dort vom Typ `SingleDevice` wäre.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

__blackjack__ hat geschrieben: Mittwoch 17. Juni 2020, 15:12 Ich meinte was ist das im C++/CLI-Quelltext für ein Typ. Denn steht ja nicht ``LibCronusMAX->SingleDevice()->IOStatusChanged`` sondern ``LibCronusMAX->IOStatusChanged`` und ich würde mich schon arg wundern wenn `LibCronusMAX` dort vom Typ `SingleDevice` wäre.
Ach, jetzt verstehe ich was du meinst! :lol:
Sorry, da habe ich mich vertippt. Ich wollte, um es für andere verständlicher machen, da nicht LibCronusMAX->SingleDevice()->IOStatusChanged' sondern '_device->IOStatusChanged' stand, was für "Außenstehende" verwirrend wäre.
xXSkyWalkerXx1
User
Beiträge: 379
Registriert: Mittwoch 27. Juni 2018, 17:39

Also...
1) Es IST C#, zum Einen an der Quelldateiendung erkennbar ('.cs'), zum Anderen anhand, weil im Quellcode 'using' statt '#include' verwendet wird.
2) Es ist echt schwer eine Lösung zu finden - ich suche bereits seit ~11 Uhr eine Lösung, hab edliche Seiten durchgeforstet. Meine Freundin leidet schon drunter. xD
Ist auch schwer einzuschätzem, ob es an meinem Code liegt:

Code: Alles auswählen

     self.device.IOStatusChanged += EventHandler[LibCronusMAX.IOStatus](self.ioChanged)

     #Obwohl der Fehler schon komisch ist...
     TypeError: unsupported operand type(s) for +=: 'NoneType' and '0, Culture=neutral, PublicKeyToken=null]]'
     
Naja, werde für heute aufhören und es morgen weiter versuchen. :D
MVS2019 updated auch gerade, so kann ich noch etwas anderes in der API ändern, um mir den Zugriff zu erweitern.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@xXSkyWalkerXx1: Es ist kein C#. Die Dateiendung kann man auch auf *.png ändern, was den Quelltext nicht zu einem Bild macht. Und wieso sollte ``using`` den Quelltext zu C# machen? Es gibt auch andere Programmiersprachen die das Schlüsselwort ``using`` verwenden. Vala beispielsweise. Unter anderem eben C++/CIL. Und das kennt im Gegensatz zu C# halt auch ein ``gcnew``-Schlüsselwort und ^ bei Typen um spezielle Zeiger zu deklarieren. Beides gibt es in C# nicht, also ist das ganz sicher kein C#.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten