Der Aufruf von C++/Qt-Klassen über C++/CLI-Wrapper ist wie ein Spaziergang im Park.Wie schreibe Wrapper-Klassen für die Zuordnung Qt-Signale zu C# -Ereignissen (über C++/CLI)
Aber ich bin stecken stecken Zuordnung von C++/Qt-Signale zu C# -Ereignissen.
Ich habe versucht, einige der verfügbaren How-Tos/Antworten zu kombinieren, aber jede Arbeitsergebnis nicht bekommen:
- How to map Qt Signal to Event in Managed C++ (C++/CLI)
- Calling managed code from unmanaged code and vice-versa
- und einige andere nicht so direkt im Zusammenhang ...
Das Problem hier ist, dass diese How-Tos/Antworten ziemlich alt sind. Ich arbeite derzeit mit Qt5.5 (bald 5.6) und .NET 4.6. Ich habe versucht, alles dem aktuellen Stand der Technik anzupassen, aber vielleicht gescheitert.
Es kann sein, dass ich den Wald nicht sehen kann, weil zu viele Bäume, so würde Ich mag für ein Arbeits Beispiel fragen, die die Aufgabe mit aktuellen Framework-Versionen erreicht, so dass ich die Unterschiede erkennen kann und lerne aus den Fehlern.
[bearbeiten] Sie können dieses Github Repo für diese Quelle auschecken. Die Teile für QtSignal to C# Event sind auskommentiert, um diesen Code in einem funktionierenden Zustand zu haben.
Github Repo: https://github.com/qwc/QtSignalToCSharpEvent
Für diejenigen, die noch alles wollen, ohne spielen um lesen ... lesen Sie weiter ... Hier mein aktueller nicht-funktionierenden Code:
So habe ich eine Klasse in rein QT5
#ifndef PUREQT_H
#define PUREQT_H
#include <QObject>
#include <QString>
#include "PureQt_global.h"
class PUREQTSHARED_EXPORT PureQt : public QObject {
Q_OBJECT
public:
PureQt(QString name);
~PureQt(){}
QString getSomeVar();
void someFunc(const QString & string);
public slots:
signals:
void someFuncWasCalled(const QString &string);
private:
QString someVar;
};
#endif // PUREQT_H
Mit folgenden eher einfachen Implementierung:
#include "PureQt.h"
PureQt::PureQt(QString name) {
this->someVar = "ctor("+name+")";
}
QString PureQt::getSomeVar() {
return this->someVar;
}
void PureQt::someFunc(const QString &string) {
this->someVar += "someFunc("+string+")";
emit someFuncWasCalled(this->someVar);
}
Dann habe ich einen verwalteten Wrapper mit C++/CLI implementiert, um den unmanaged Code von C# aufrufen zu können. Seien Sie sich bewusst, dass ich bereits versucht habe, Code hinzuzufügen, um das Ereignismanagement zu signalisieren.
#pragma once
#include "conversion.h"
#include "../pureqt/PureQt.h"
#include "SignalProxy.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
namespace ManagedCppQtSpace {
// different variants... from tinkering around.
delegate void someFuncWasCalled(String^);
delegate void someFuncWasCalledU(QString str);
[StructLayoutAttribute(LayoutKind::Sequential)]
public ref struct DelegateWrapper {
[MarshalAsAttribute(UnmanagedType::FunctionPtr)]
someFuncWasCalledU^ delegate;
};
public ref class ManagedCppQt
{
public:
ManagedCppQt(String^ name){
pureQtObject = new PureQt(StringToQString(name));
proxy = new SignalProxy(pureQtObject);
wrapper = gcnew DelegateWrapper();
wrapper->delegate = gcnew someFuncWasCalledU(this, ManagedCppQt::signalCallback);
signalCallbackProxy callbackproxy;
Marshal::StructureToPtr(wrapper, callbackproxy, false); // currently im stuck here with a compile error, but the problem may lie somewhere else...
proxy->setCallback(callbackproxy);
};
~ManagedCppQt(){
delete pureQtObject;
};
event someFuncWasCalled^someFuncCalled;
void someFunc(String^ string){
pureQtObject->someFunc(StringToQString(string));
};
String^ getSomeString() {
return QStringToString(pureQtObject->getSomeVar());
}
void signalCallback(QString str) {
someFuncCalled(QStringToString(str));
}
DelegateWrapper^wrapper;
private:
PureQt * pureQtObject;
SignalProxy * proxy;
};
}
So zum Verbindungssignal und Schlitz von Qt mit einem Rückruf Handhabung, die ein Ereignis in verwaltetem Code zu erhöhen Lage ist, einige werden eine Proxy-Klasse benötigen, wenn es keine Option ist den Basis-Code zu ändern (weil es auch in verwendet werden andere nicht verwaltete C++ - Projekte).
#ifndef SIGNALPROXY_H
#define SIGNALPROXY_H
#include <QObject>
#include "../pureqt/PureQt.h"
typedef void (*signalCallbackProxy) (QString str);
class SignalProxy : public QObject
{
Q_OBJECT
public:
explicit SignalProxy(PureQt* pqt);
~SignalProxy();
void setCallback(signalCallbackProxy callback);
signals:
public slots:
void someFuncSlot(QString str);
private:
PureQt* pureQt;
signalCallbackProxy scallback;
};
#endif // SIGNALPROXY_H
Mit Umsetzung:
#include "SignalProxy.h"
SignalProxy::SignalProxy(PureQt* pqt){
pureQt = pqt;
this->connect(pureQt, SIGNAL(PureQt::someFuncWasCalled(QString)), this, SLOT(someFuncSlot(QString)));
}
SignalProxy::~SignalProxy()
{}
void SignalProxy::setCallback(signalCallbackProxy callback){
this->scallback = callback;
}
void SignalProxy::someFuncSlot(QString str){
if(this->scallback != NULL)
this->scallback(str);
}
So. Nun, wie Sie diese beiden Welten, Qt-Signale -> verwaltete .NET-Ereignisse richtig zu verknüpfen?
Ich habe auch versucht, einige einfache Ansätze, die Fehler zu kompilieren führen, wie:
QObject::connect(pureQtObject, &PureQt::someFuncWasCalled, &MangagedCppQtSpace::ManagedCppQt::signalCallback);
anstelle der Proxy-Klasse oder mit einer Lambda-Funktion:
QObject::connect(pureQtObject, &PureQt::someFuncWasCalled, [] (QString str) {
signalCallback(str);// or ManagedCppQt::signalCallback, but for this the method has to be static, and it isn't possible to raise events from static methods...
}
Können Sie genauer angeben, was Sie stolpern lässt? Erhalten Sie Kompilierungsfehler? Laufzeitfehler? Keine Fehler, aber die Ereignisse feuern nicht? –
Sie müssen zwei Dinge tun: 1. Deklarieren Sie den Event-Handler als Mitglied Ihrer Klasse. 2. Rufen Sie den Event-Handler von einem Slot (ein Lambda, wirklich) auf, der mit Ihrem Signal verbunden ist. Das ist wirklich alles, was dazu gehört. –
"könnte meinen aktuellen Beispielcode einfügen, aber ich denke, das würde Leser nur verwirren ..." Das ist genau das, was Sie tun müssen, um diese Frage zum Thema beizubehalten. Ansonsten ist es ein direktes Duplikat. –