[gelöst]C#-Callback-function in C++/Cli

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 11.01.2017, 15:51

Das Problem ist mir noch nicht untergekommen, scheinbar ist dieser Fall abgedeckt.
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon Krishty » 11.01.2017, 22:41

Du hast recht:
https://blogs.msdn.microsoft.com/cbrumme/2003/05/06/asynchronous-operations-pinning/ hat geschrieben:Clearly the unmanaged function pointer must refer to a fixed address. It would be a disaster if the GC were relocating that! This leads many applications to create a pinning handle for the delegate. This is completely unnecessary. The unmanaged function pointer actually refers to a native code stub that we dynamically generate to perform the transition & marshaling. This stub exists in fixed memory outside of the GC heap.
Dann verdränge ich den Gedanken mal ganz schnell wieder aus meinem Kopf, und aus meinem Code … :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
 
Beiträge: 6588
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 12.01.2017, 09:40

Ich habe gerade gesehen, dass ich das ja schon mache.

Code: Ansicht erweitern :: Alles auswählen

if (mCallback == NULL)
{
mCallback = new MyCallBack();
mCallback->setCallBack(funcPtr); // <= hier übergebe ich ja den Funktionspointer der Klasse MyCallback.
}
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 12.01.2017, 10:15

ja und der funktionspointer wird WO gespeichert? Es geht nicht darum, dass du die klasse, die den funktionspointern nutzt, vorm aufräumen schützt, sondern den funktionspointer an sich!

also schön brav funcPtr in eine member-variable von mCallback legen, am besten in mCallback::setCallbackFunc
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 12.01.2017, 10:18

Aber das mache ich doch schon!!!
Über die Funktion setCallBack übergebe ich den Funktionspointer der Klasse MyCallback. Und diese bleibt am leben...
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 12.01.2017, 11:14

Nachtrag:

Anscheinend funktioniert das aufrufen des Funktionspointer nicht richtig.

Code: Ansicht erweitern :: Alles auswählen

void OPCDAGroup::enableAsynch(CallbackFunc^ theCallback)
{
        auto funcPtr = static_cast<FunctionPointer>(Marshal::GetFunctionPointerForDelegate(theCallback).ToPointer());

        if (mCallback == NULL)
        {
                mCallback = new MyCallBack();
                mCallback->setCallBack(funcPtr);
        }

        mGroup->enableAsynch(*mCallback);
// Ich habe mal testweise hier den Funktionspointer aufgerufen.
        array<OPCDAItemData^>^ arr = gcnew array<OPCDAItemData^>(10);
        funcPtr(arr); // <= Hier knallt es. also scheint dieser Funktionspointer nicht richtig zu sein!!!
//*******************************
        // Sorgt dafür, dass das Delegate nicht vorzeitig vom Garbage Collector eingesammelt wird
        GC::KeepAlive(theCallback);
}

 
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 12.01.2017, 12:10

Ich habe irgendwie das Gefühl, dass das hier nicht richtig ist
Code: Ansicht erweitern :: Alles auswählen

typedef void(*FunctionPointer)(array<OPCDAItemData^>^ arr);
 


Das aufrufen des Delegate funktioniert ja, nur eben nicht das Aufrufen über den Funktionspointer :?
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 12.01.2017, 12:51

Die Doku besagt, dass ein native function pointer keine managed-objekte enthalten darf. Von daher solltest du das Array wohl als native Datentypen übertragen. Da musst du eventuell umbauen.
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 12.01.2017, 14:42

Na ganz toll!!!! PRIMA!!!
Ich überlege schon die ganze Zeit wie ich das Problem jetzt löse, also wie ich das umbauen soll....und mir fällt da nix ein.
Ich habe es bis jetzt so gemacht, das ich eine unmanaged Struktur habe, die alle geänderten Items speichert in eine List.
Nun frage ich mich, wie ich das anstelle, dass bei diesem Event eine funktion der managed Klasse aufgerufen werden kann.
Dieser Funktion würde ich gerne diese Liste der unmanaged Items übergeben, welche ich ja in einer unmanaged klasse generiert habe.
Nur ist das Problem, dass ich aus einer unmanaged Klasse keine Funktion aufrufen kann einer managed Klasse.!!!!!
FUUUU....

Nachtrag:
Aber ich glaube, das hier ist so etwas was ich bräuchte.
https://msdn.microsoft.com/de-de/librar ... x#Anchor_1
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 13.01.2017, 09:19

MISSION ACCOMPLISHED

34477803.jpg
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 14.01.2017, 10:59

Scheint wohl endlich zu klappen?!

Gratulation!
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 16.01.2017, 09:01

Japp!! Hörnse uff...das war ein rumgehacke^^
Mein größtes Problem war ja, wie bekomme ich die unmanaged Datentypen in managed Code.
Ist jetzt etwas kompliziert zu erklären, aber nach einiger Googlezeit fand ich dann das hier:
Mist, finde den Link nicht mehr...
Dann halt etwas Code:

Eine Wrapper-Klasse die die umwandlung der unmanaged Daten in managed Daten macht.
Ich habe meine ganze Kreativität rausgelassen, und diese Klasse "Wrapper" genannt...
Code: Ansicht erweitern :: Alles auswählen

class Wrapper
{
private:
        IntPtr m_handle;

public:
        Wrapper()
        {}

        ~Wrapper()
        {
                static_cast<GCHandle>(m_handle).Free();
        }

        void makeManagedArray(OPCDAItemDataUnmanaged list[], const unsigned int& countListEntry)
        {
                array<OPCDAItemData^>^ arr = gcnew array<OPCDAItemData^>(countListEntry);

                for (int index(0); index < countListEntry; ++index)
                        arr[index] = gcnew OPCDAItemData(list[index].mData, list[index].mName);

                safe_cast< CallbackFunc ^ >(static_cast<GCHandle>(m_handle).Target)(arr); // <= Diese Stelle ist das entscheidende! Von hier aus wird das Delegate (also C#-Funktion) aufgerufen
        }

        void setDelegate(CallbackFunc^ delegateFunc)
        {
                m_handle = static_cast<IntPtr>(GCHandle::Alloc(delegateFunc));
        }
};
 


Dann static Wrapper wrapper; im Header (öffentlicher Namensraum) um die Instanz in der Klasse zu verwenden, die als Callbackklasse von der Bibliothek genutzt wird.
Ich weiß jetzt garnicht ob das static erforderlich ist...

Und dann in dieser besagten Callback-Klasse:
Code: Ansicht erweitern :: Alles auswählen

class MyCallBack : public IAsynchDataCallback
{
public:
        void setDelegate(CallbackFunc^ delegateFunc)
        {
                wrapper.setDelegate(delegateFunc);
        }

        void OnDataChange(COPCGroup &group, CAtlMap<COPCItem*, OPCItemData*> &changes)
        {
                array<OPCDAItemData^>^ arr = gcnew array<OPCDAItemData^>(changes.GetCount());
                POSITION pos;
                COPCItem* key;
                OPCItemData* value;
                pos = changes.GetStartPosition();

                int index(0);

                OPCDAItemDataUnmanaged* list = new OPCDAItemDataUnmanaged[changes.GetCount()];

                while ( pos != NULL )
                {
                        key = changes.GetKeyAt(pos);
                        value = changes.GetNextValue(pos);
                        list[index] = OPCDAItemDataUnmanaged(value, key->getName());
                        ++index;
                }
                wrapper.makeManagedArray(list, changes.GetCount());
        }
};
 


Und Voila. Jochen hat sich gefreut wie sonstwas....

Hintergrund sollte ja der sein, dass eine C#-Funktion immer dann aufgerufen werden muß wenn sich Werte auf dem OPC-Server ändern.
Die C++-Bibliothek biedet dazu ein Callback-Klassen-Interface; also davon erben, Methode implementieren, und instanz der Klasse an die Bibliothek übergeben. Ganz leicht.
Nun aber sollte aus dieser Callback-Klasse ja ein Delegate aufgerufen werden....und dies gestaltete sich echt als schwierig, da ja zB in einer unmanaged Klasse keine managed Klassenhandler oder Delegates erlaubt sind. Deswegen der Umweg über diesen....naja...."Pointer"(?)...und Wrappen.

Jau. Danke noch mal für die Hilfe...


Nachtrag:
Ich sehe gerade, dass ich mir wahrscheinlich diese statische Instanz der Wrapper-Klasse im header hätte sparen können.
Ich könnte sie evtl auch als Member in MyCallback packen.
nur frage ich mich, wieso ich das nicht gemacht habe.... :?:
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 17.01.2017, 09:39

Nachtrag:
Oh man...ich habe es mir ja so umständlich gemacht, und vollkommen...blöd.
*peinlich*

Hier mal das vereinfachte Vorgehen:
Code: Ansicht erweitern :: Alles auswählen

class MyCallBack : public IAsynchDataCallback
{
private:
        IntPtr mHandle;
public:
        void setDelegate(CallbackFunc^ delegateFunc)
        {
                mHandle = static_cast<IntPtr>(GCHandle::Alloc(delegateFunc));
        }

        void OnDataChange(COPCGroup &group, CAtlMap<COPCItem*, OPCItemData*> &changes)
        {
                array<OPCDAItemData^>^ arr = gcnew array<OPCDAItemData^>(changes.GetCount());
                POSITION pos;
                COPCItem* key;
                OPCItemData* value;
                pos = changes.GetStartPosition();

                int index(0);
                while ( pos != NULL )
                {
                        key = changes.GetKeyAt(pos);
                        value = changes.GetNextValue(pos);
                        arr[index] = gcnew OPCDAItemData(value, key->getName());
                        ++index;
                }
                safe_cast<CallbackFunc^>(static_cast<GCHandle>(mHandle).Target)(arr);
        }
};
 


Ja...was soll ich sagen, manchmal baue ich ganz schön mist im code... :?

Mal zusammenfassen was *ich* hier mache.
Dieses GCHandle::Alloc(Object) reserviert einen Speicherbereich im managed-Speicher für ein Object und gibt ein Handle darauf zurück, und verhindert natürlich das es vom GC eingesammelt wird...
Und zu dieser Zeile:
safe_cast<CallbackFunc^>(static_cast<GCHandle>(mHandle).Target)(arr);
Dieses Target:
MSDN hat geschrieben:Ruft das Objekt ab, das von diesem Handle dargestellt wird, oder legt dieses fest.

Es wird also das Delegate aufgerufen und das managed Array übergeben...
:)
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 17.01.2017, 13:40

Mal ne ganz blöde frage: Warum wandelst du das GCHandle in einen IntPtr um und wieder zurück? Das könnte man auch noch weg lassen...
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 17.01.2017, 14:42

Warum? Na damit du blöden fragen stellen kannst^^

Aber ja, stimmt. Ich kann auch gleich ein GCHandle als Member verwenden.
Habe es gerade geändert...
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon biertrinker » 17.01.2017, 17:43

Ich versteh gar nicht, wozu du überhaupt ein GCHandle brauchst. Wenn du das Delegate als Member speicherst, hat der Garbage Collector eine Referenz darauf, die so lange gültig ist wie die Lebensdauer der MyCallback Instanz.
biertrinker
 
Beiträge: 2
Registriert: 24.09.2006, 22:06

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 20.01.2017, 08:55

Sorry, ich war unpässlich die letzten 2 Tage...

biertrinker hat geschrieben:Ich versteh gar nicht, wozu du überhaupt ein GCHandle brauchst. Wenn du das Delegate als Member speicherst, hat der Garbage Collector eine Referenz darauf, die so lange gültig ist wie die Lebensdauer der MyCallback Instanz.

Ich kann das Delegate nicht als Member speichern. Zumindest sagt mir das der Compiler. Kannst es mal probieren....
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 20.01.2017, 10:09

Welche Fehlermeldung kommt?
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 20.01.2017, 10:14

VC hat geschrieben:ein Member einer nicht-verwaltet-Klasse kann kein Handle sein
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 20.01.2017, 10:21

Kannst du die klasse nicht einfach verwaltet machen? Würde mit C++/CLI native Klassen soweit es geht vermeiden
Duct tape is like the force. It has a light side, a dark side, and it holds the world together.
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1176
Registriert: 07.10.2012, 14:56

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 20.01.2017, 10:33

Nein, kann ich nicht. Ich übergebe ja eine Instanz davon einer C++-Bibliothek.
Aber ist ja auch nicht sooo schlimm. Ist halt nur ein kleiner Umweg so ;)
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 13.02.2017, 11:50

Und wieder ein Problem vor dem ich stehe!!

Wenn ich mein Projekt, welches ja eine managed Bibliothek werden soll, mit Debug erstelle, funktioniert alles gut.
Wenn ich das Projekt aber als Releas erstellen will, sagt mir VS:

Fehler LNK2038 Konflikt ermittelt f³r "RuntimeLibrary": Der Wert "MT_StaticRelease" stimmt nicht mit dem Wert "MD_DynamicRelease"


Wieso funktioniert das im Debug-Mode, aber nicht im Release-Mode?
Die Bibliothek die ich verwenden möchte, wird für statisches Linken erstellt.
Ich würde sie ja auch dynamisch als DLL erstellen, nur wird mir NUR eine DLL ausgespuckt, und die kann ich ja nicht in meinem Projekt verwenden; zumindest braucht man doch da eine LIB-File, oder irre ich mich??
Zuletzt geändert von joggel am 13.02.2017, 12:32, insgesamt 1-mal geändert.
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: [gelöst]C#-Callback-function in C++/Cli

Beitragvon joggel » 13.02.2017, 12:32

Ehm...ich weiß nicht was ich da versucht habe zu erstellen, aber jetzt geht es.
Also letzter Post kann ignoriert werden^^
bald mit neuem Avatar
Benutzeravatar
joggel
Establishment
 
Beiträge: 1350
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Vorherige

Zurück zu Programmiersprachen, Quelltext und Bibliotheken

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot], Google [Bot] und 3 Gäste