[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.

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

Beitragvon joggel » 18.10.2016, 13:23

Hallo ZFXler,

ich stehe hier vor einem Problem.

Ich möchte ja einen Teil einer C++-Bibliothek nach C# portieren.
Ich habe mir dazu einen Wrapper in C++/Cli geschrieben, in der ich Funktionen der instanziierten Klasse(n) aufrufe.
Ich so weit ist das klar.
Jetzt möchte ich auf C++-Seite eine Callback-Funktion, die in C# geschrieben ist, aufrufen.
Also quasi wie so etwas hier:
C#
Code: Ansicht erweitern :: Alles auswählen

void MyCallbackFunction(int[] param)
{
 doSomethingWithParam(param);
}

static void Main(string[] args)
{
 MyDLLClass theClass = new MyDLLClass();
 theClass.setCallbackFunc(MyCallbackFunction);
 while(theClass.isRunning)
 {
  theClass.doSomething();
 }
}
 

Die Idee ist dahinter, dass dieses doSomething u.U. die Callback-Funktion aufrufen muss, und ihr ein array mit Integerwerten übergeben.

Ich hoffe mein Problem ist verständlich.
Was muss ich auf C# machen?
Was auf C++/ClI seite und was auf C++-Seite???

Hat jemand dazu erfahrung?
MasterQ? :)
Zuletzt geändert von joggel am 19.10.2016, 14:30, insgesamt 1-mal geändert.
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon Krishty » 18.10.2016, 13:38

  Marshal.GetFunctionPointerForDelegate(yourCSharpCallback)

Wir speichern keine direkten Callback-Zeiger, sondern legen sie in ein struct, und das muss ordentlich im Speicher gepinnt werden, damit es der GC nicht aufräumt, während es läuft. Ob das auch bei direkten Funktionszeigern nötig ist, kA. (Ich denke, schon.)

  GCHandle callbackPinned = GCHandle.Alloc(callbacks, GCHandleType.Pinned);
  IntPtr forCplusplus = callbackPinned.AddrOfPinnedObject();
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
 
Beiträge: 6654
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 18.10.2016, 13:44

Okay, ich probiere das mal.

Und wie würde die Signatur in C++ ausehen müssen?
Also:
IntPtr forCplusplus = callbackPinned.AddrOfPinnedObject();
myCPlusPlusClass->setCSharpCallBackFunc(forCplusplus);
Wie soll dann die Signatur von setCSharpCallBackFunc aussehen?
Zuletzt geändert von joggel am 18.10.2016, 14:03, insgesamt 2-mal geändert.
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon Krishty » 18.10.2016, 14:00

Ist eigentlich beliebig, weil das Delegate das Hinbiegen von Calling Convention usw. übernimmt. Ich hab’s aber bisher nur mit static int function(IntPtr parameter) probiert.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
 
Beiträge: 6654
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 18.10.2016, 14:06

Ich bin mal wieder Noob in sachen Funktionspointer.
Ich meinte, wie sollte die Signatur auf C++-Seite aussehen?
So in etwa?
setCallBackFunc(void (*)(int**))
Ist das so korrekt?

Also, ich möchte ja ein Array mit ints übergeben...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 18.10.2016, 14:55

Oder anders gefragt:
Wenn ich den Pointer habe:

IntPtr forCplusplus = callbackPinned.AddrOfPinnedObject();

Wie rufe ich jetzt die Callback-Funktion aus C++ heraus auf?
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon Krishty » 18.10.2016, 15:49

Das kommt alles drauf an, wie die Signatur deiner C#-Funktion aussieht! Ist die Signatur z.B. static int foo(int), dann deklarierst du auf C++-Seite:

  using SetCallBackFunc = int __stdcall (int);
  auto toCallback = reinterpret_cast<SetCallBackFunc *>(der_intptr_der_aus_CSharp_kommt);
  auto returnValue = (*toCallback)(123);


__stdcall ist Standard-Calling Convention für C# & Co (weil COM und die WinAPI drauf aufsetzen), falls dein C++-Code aber unbedingt was anderes erwartet, kannst du das irgendwie via Attribut vor der C#-Funktion einstellen.

Ich empfehle auch stark, den Debugger so umzustellen, dass du C# und C++ gleichzeitig debuggen kannst. Das macht Visual C++ per default NICHT, man muss es erst irgendwo einstellen (Google weiß, wo). Ist ne Hilfe :)
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
 
Beiträge: 6654
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 18.10.2016, 15:57

Alles klar.
Hilft mir schon weiter. Danke!!
Werd es morgen mal testen...jetzt ist mein Kopf zu leer (nach 8h dauerknobeln :| )^^

Das mit dem Umstellen werd ich mal googlen: wäre echt angenehmer...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 18.10.2016, 16:18

Compiler sagt "nein".
Code: Ansicht erweitern :: Alles auswählen

void TheClass::setCallback(CallBackFunc^ theCallback)
{
        IntPtr ip = Marshal::GetFunctionPointerForDelegate(theCallback);

        array<int^>^ list;

        using SetCallBackFunc = int __stdcall (array<int^>^);
        auto toCallback = reinterpret_cast<SetCallBackFunc*>(ip.ToPointer());
        auto returnValue = (*toCallback)(list);
}
 

Ich wollte lediglich nur mal ausporieren, ob meine Funktion in C# aufgerufen wird, aber der Compiler haut mir hier die cast Zeile um die Ohren, mit folgender Begründung:

Fehler C2440 "Initialisierung": "SetCallBackFunc (__stdcall *)" kann nicht in "int (__stdcall *)(cli::array<System::Int32 ^,1> ^)" konvertiert werden

:?:
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon Krishty » 18.10.2016, 16:27

Ah, du bekommst direkt einen GCNew-Zeiger zu der Funktion? Dann kann man die bestimmt irgendwie direkt aufrufen, ohne Funktionszeiger-Hin-und-Her.

Da musst du aber wen anders fragen, mit CLI-Syntax kenne ich mich nicht aus …
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
 
Beiträge: 6654
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 18.10.2016, 16:31

Ich möchte das ja dann an meinen unmanaged C++-Teil übergeben, und dort die Funktion aufrufen.
Also das Casten und so, werde ich bestimmt schon brauchen....

MasterQ weiß vlt etwas darüber, könnte ich mir vorstellen...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

Re: C#-Callback-function in C++/Cli

Beitragvon MasterQ32 » 18.10.2016, 23:35

Klar hat der Meister da was:

Zur Managed-Seite, hier der Part in C#:
Code: Ansicht erweitern :: Alles auswählen

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] // Hier deine gewünschte Calling Convention
public delegate int MyCallback([MarshalAs(UnmanagedType.        LPArray)] int[] values);

public class Methods
{
    static MyCallback callback;
    public static IntPtr GetCallback() {
        if(callback == null)
            callback = MyImplementation; // Musst du bereit stellen
        return Marshal.GetFunctionPointerForDelegate(callback); // Liefere IntPtr auf Delegat zurück
    }
}
 

Dazu ein paar Anmerkungen:
  • Das Attribut am Delegattyp ist nicht zwangsweise relevant, ist aber wärmstens zu empfehlen, da du so Klarheit schaffst.
  • Marshal.GetFunctionPointerForDelegate ist der Weg, eine C#-"Methode" in einen Funktionspointer umzusetzen. Das ganze geht aber eben nur mit Delegaten, und darum:
  • Die Funktion liefert einen Pointer für den angegebenen Delegaten zurück. Sobald dieser vom Garbage Collector erfasst wird, ist der Pointer ungültig! Darum auch die Caching-Variable.
  • MarshalAs sorgt dafür dafür, dass das Array als C-Array übergeben wird (hier also int*). Falls die Länge des Arrays relevant sein sollte, musst du diese noch als zusätzlichen Parameter übergeben.

Nun der nicht verwaltete Teil:
Code: Ansicht erweitern :: Alles auswählen
using MyCCallback = int __cdecl (*) (int * array);

void someFunc(IntPtr ^ptr)
{
    auto myCallback = static_cast<MyCCallback>(ptr.ToPointer()); // reinterpret_cast doch bitte NUR bei virtueller Vererbung ;)
    int data[] = { 1, 2, 3, 4 };
    int result = myCallback(data);
}
 


Bitte beachten: Nichts des ganzen wurde irgendwie getestet, kann also noch Fehler enthalten. Ich bin aber gerne für Rückfragen da ;)

Grüße
Felix
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

Re: C#-Callback-function in C++/Cli

Beitragvon biertrinker » 19.10.2016, 00:10

Ohne die C++ Deklaration deines Funktionszeigers zu kennen und wie sich das Array zusammensetzt, kann man schlecht weiterhelfen.

Generell muss man bei so einem Reverse Interop allerdings ein paar Dinge beachten.
1. Die Callilng Convention muss passen
2. Die Parameter müssen stimmen (bei Arrays nicht ganz einfach)
3. Die Delegate Instanz muss erreichbar bleiben, da sie sonst vom Garbage Collector eingesammelt wird, während der zugehörige Funktionszeiger auf der C++ Seite noch in Gebrauch ist (Den Funktionszeiger, der von Marshal::GetFunctionPointerForDelegate zurückgegben wird, muss man allerdings nicht pinnen)

Wie die Deklaration des Delegates aussehen muss, kommt darauf an wie der Funktionszeiger in der deiner C++ Bibliothek deklariert ist und wie sich das Array zusammensetzt. Ich mach mal ein einfaches Beispiel: (Bin allerdings nicht so firm mit der C++/CLI Syntax, deshalb bitte nicht gleich copy und pasten)

Nehmen wir an, es gibt folgenden C++ Code
Code: Ansicht erweitern :: Alles auswählen

// Im header
typedef void (*FunctionPointer)(int args[]);
void invoke(FunctionPointer func);

// In cpp Datei
void invoke(FunctionPointer func)
{
    int[] nums = {1, 2, 3, 4};
    func(nums);
}
 


Dann sieht das entsprechende Delegate für FunctionPointer in C++/CLI so aus:

Code: Ansicht erweitern :: Alles auswählen

[UnmanagedFunctionPointer (CallingConvention::Cdecl)]
delegate void CallbackFunc ([MarshalAs(UnmanagedType::LPArray, SizeConst = 4)] array<int>^ args);
 


Die Calling Convention wird hier mit Cdecl angegeben, weil das die Standard-Konvention in C++ ist, wenn der Funktionszeiger nicht explizit als __stdcall deklariert wird. Managed Arrays haben eine vorgegebene Länge, allerdings weiß der Interop Marshaler nicht wie groß das C++ Array ist, weshalb man dies mit SizeConst angeben muss. Wenn die Größe erst zur Laufzeit bekannt ist, muss man zusätzlich einen Längen Parameter einführen und den SizeParamIndex angeben.

Auf der C++/CLI Seite lässt sich das folgendermaßen aufrufen

Code: Ansicht erweitern :: Alles auswählen


// header der C++ Lib einbinden

void TheClass::invokeCallback(CallBackFunc^ theCallback)
{
    auto funcPtr = static_cast<FunctionPointer>(Marshal::GetFunctionPointerForDelegate(theCallback).ToPointer());
   
    // Aufruf der C++ Funktion
    invoke(funcPtr);
   
    // Sorgt dafür, dass das Delegate nicht vorzeitig vom Garbage Collector eingesammelt wird
    GC::KeepAlive(theCallback);
}
 


Wenn der Aufruf deines Callbacks asynchron ist oder deine C++ Bibliothek den Funktionszeiger über längere Zeit speichert, solltest du das Delegate in deiner Wrapper Klasse als Member speichern.
biertrinker
 
Beiträge: 2
Registriert: 24.09.2006, 22:06

Re: C#-Callback-function in C++/Cli

Beitragvon joggel » 19.10.2016, 07:49

MasterQ32 hat geschrieben:Klar hat der Meister da was:

Wußte ich doch :D
Ich werde mir das alles mal in Ruhe anschauen und probieren, auf jeden Fall sieht es danach aus was ich brauche. Danke!!
Falls ich noch Fragen habe, frage ich...oder ich weiß ja wo Du im WWW "rumhängst" => IRC ^^

@Biertrinker
Das sieht mir auch brauchbar aus. Was mich jedoch etwas stört ist, dass ich die Größe es Arrays eben nicht zur Laufzeit kenne, aber da hast Du ja einen Link dazu....muss ich mal schauen.
Wenn der Aufruf deines Callbacks asynchron ist oder deine C++ Bibliothek den Funktionszeiger über längere Zeit speichert, solltest du das Delegate in deiner Wrapper Klasse als Member speichern.

Ja, der Funktionszeiger wird über längeren Zeitraum gespeichert, also werd ich das wohl mal machen.

Jo, danke erstmal...ich würde mich bei weiteren fragen noch mal melden...


Nachtrag:
Es funktioniert!! :)
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon joggel » 02.11.2016, 09:01

Noch eine Frage: Habe ich etwas besonderes zu beachten, wenn ich statt ein array von ints, ein array von einer managed Klasse zurückgeben will?
Weil das mit dem int-array funktioniert, wenn ich jedoch eine array einer managed-Klasse über die callbackfunktion zurückgeben möchte, funktioniert es nicht...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon MasterQ32 » 02.11.2016, 10:41

Managed-Klassen gehen nicht.

Was geht, findest du hier: Marshaling Classes, Structures, and Unions

Du kannst Structs zurückgeben, auch Arrays von Structs. Aber alles nur mit "call-by-value"
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

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

Beitragvon joggel » 02.11.2016, 10:44

MasterQ32 hat geschrieben:Managed-Klassen gehen nicht.

Noooooooo :(

Okay, ich schaue mal wie ich das löse. Danke!
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon MasterQ32 » 02.11.2016, 14:16

Was hast du denn genau vor?
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

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

Beitragvon joggel » 02.11.2016, 14:52

Fällt mir schwer das jetzt auch so wiederzugeben. Aber ich versuche es mal...

Ich möchte ja Teile einer C++-Bibliothek, oder besser gesagt, ein paar Funktionalitäten nach C# portieren.
Um genauer zu sein, geht es um einen OPC-Client, der ganz simpel nur Variablen von einem OPC-Server lesen oder schreiben soll.
Es gibt dabei auch eine Funktionalität, bei dem der Server den Clienten benachrichtigt wenn sich eine Variable ändert, und zwar übergibt man der C++-Bibliothek dann eine bestimmte abgeleitete Klasse als "Callback-Klasse". Sobald sich die bestimmten Variablen auf dem OPC-Server ändern, wird die (überschrieben) Funktion der "Callback-Klasse" aufgerufen.
Nun dachte ich mir eben, ich schreibe mir so eine Callback-Klasse und implementiere in die Aufruffunktion so, dass sie meine C#-Funktion aufruft...also mit einem Funktionspointer.
Die Aufruffunktion hat folgende Signatur:
Code: Ansicht erweitern :: Alles auswählen

MyCallbckClass::onItemChange(CAtlMap<COPCItem *, OPCItemData *>& changes)
{
// hier dann der C#-Funktionsaufruf mit den Änderungen
}
 

Ich hatte jetzt auch die Klasse COPCItem als managed Klasse gewrapped, und die OPCItemData auch.
Aber eigentlich sind die relevanten Information NUR in OPCItemData. Was ich eigentlich auch als struct kapseln kann, was ich bestimmt auch bei Gelegenheit machen werde...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon MasterQ32 » 02.11.2016, 16:15

Ja, in dem fall wirst du wohl eher IN der onImteChange einfach Managed Code verwenden, und das Array übersetzen. Das dürfte dir Stress sparen
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

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

Beitragvon joggel » 02.11.2016, 17:06

That's the plan...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon joggel » 10.01.2017, 12:38

Huhu,

ich muß noch mal das Thema rauskramen.

Ich bekomme es nämlich nicht hin :(

Mir kommt es so vor, als wird diese onItemChange-Funktion irgendwie nicht aufgerufen.

Habe ich das hier richtig gemacht?
Code: Ansicht erweitern :: Alles auswählen

        [UnmanagedFunctionPointer(CallingConvention::Cdecl)]
        public delegate void CallbackFunc(array<OPCDAItemData^>^ args);
 

OPCDAItemData ist eine managed struktur.

HELP!!!
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon MasterQ32 » 10.01.2017, 17:03

Könntest du mal ALLE relevanten Codestellen zu deinem Problem posten? Das würde einige Sachen massiv vereinfachen. Das oben ist ja irgendwie ein Mashup aus C# und C++/CLI, von daher ;)
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

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

Beitragvon joggel » 10.01.2017, 17:30

Jo, sorry.
Wollte ich gerade auch machen...aber du warst schneller.

Aaaaalso:
Hier in dieser Funktion scheint es immer einen Ausnahmefehler oder so zu geben.
Code: Ansicht erweitern :: Alles auswählen

        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);
                        ++index;
                }

                mFunctionPtr(arr); // <= ich denke mal hier läuft irgend etwas schief. Wie der Name es schon sagt, ist das der Funktionspointer, dem ich das Array überegeb
}
 

Der Funktionspointer ist wie folgt deklariert:
Code: Ansicht erweitern :: Alles auswählen

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


Und hier ...(wie sagt man dazu?) die CallbackFunction-Deklaration
Code: Ansicht erweitern :: Alles auswählen

        [UnmanagedFunctionPointer(CallingConvention::Cdecl)]
        public delegate void CallbackFunc(/*[MarshalAs(UnmanagedType::LPArray, SizeConst = 5)]*/ array<OPCDAItemData^>^ args);
 



So, ich habe jetzt erstmal Feierabend. Ich hoffe ich habe alles hier geschrieben.
Wünsch euch was :)
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon MasterQ32 » 11.01.2017, 09:52

Zwei Sachen: Ist der Funktionspointer mFunctionPtr != nullptr und hast du deinen Delegaten, den du in den Funktionspointer marshalst, auch brav vom GC eingesammelt zu werden abgehalten (durch das Halten einer Referenz auf das Objekt)?
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

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

Beitragvon joggel » 11.01.2017, 09:59

Guten Morgen,

ob mFunctionPtr != nullptr ist, muß ich mal prüfen, denke aber schon das er nicht NULL ist.

und hast du deinen Delegaten, den du in den Funktionspointer marshalst, auch brav vom GC eingesammelt zu werden abgehalten (durch das Halten einer Referenz auf das Objekt)?

Denke habe ich auch. Mittels GC::KeepAlive(theCallback);

Hier mal der Code, also die Funktionsimplementation wo ich den Delegate überge

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);

        // Sorgt dafür, dass das Delegate nicht vorzeitig vom Garbage Collector eingesammelt wird
        GC::KeepAlive(theCallback);
}
 

Ich hoffe Du kannst das alles halbwegs nachvollziehen was ich hier schreibe; ist, glaube ich, alles ziemlich verwoben und so....
Vlt kann ich Dir ja auch mal das Projekt zuschicken oder so....natürlich nur, wenn du magst und ne freie minute hast...
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon joggel » 11.01.2017, 10:54

Nachtrag:
Diese Fehlermeldung schmeißt mir VS um die Ohren. Kann ich aber wenig damit anfangen
Fehler.png


Weitere Meldung:
Weitere Informationen finden Sie unter: Die Laufzeit hat einen schwerwiegenden Fehler entdeckt. Fehleradresse: "0x7399020d" in Thread "0x3c0". Fehlercode: 0xc0000005. Bei diesem Fehler könnte es sich um ein Problem in der CLR oder in den unsicheren oder nicht verifizierbaren Teilen des Benutzercodes handeln. Übliche Ursachen dieses Bugs sind Marshallerfehler für COM-Interop oder PInvoke, die den Stapel beschädigen können.
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon MasterQ32 » 11.01.2017, 14:45

GC::KeepAlive(...) tut nicht das, was du erwartest. Das verhindert nur die Garbage Collection bis zum Call der Funktion. Du musst den theCallback in einer Membervariable eines lebendigen Objektes zwischenspeichern, bis du den Callback nicht mehr benötigst.
Wer checkt diese Shaderprogrammierung denn?
JCL: Kein Mensch zwingt Sie jedoch, mit Shadern oder ueberhaupt mit Gamestudio zu arbeiten. Es gibt schliesslich auch andere schoene Hobbies, wie zum Beispiel das Sammeln von Bierdeckeln – JCL quotes
Benutzeravatar
MasterQ32
Felix Queißner
Establishment
 
Beiträge: 1194
Registriert: 07.10.2012, 14:56

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

Beitragvon joggel » 11.01.2017, 14:50

Achso. Okay, werd ich dann mal ausprobieren.
Ich sag bescheid, ob es geklappt hat.
CEO of Dirty Codez Production®
Benutzeravatar
joggel
Establishment
 
Beiträge: 1364
Registriert: 06.11.2007, 19:06
Wohnort: Dresden

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

Beitragvon Krishty » 11.01.2017, 15:08

Reicht das denn? Könnte der GC nicht auch den Speicher kompaktieren, während die Funktion ausgeführt wird, und sie dabei an einen neuen Ort verschieben? Ich jedenfalls musste sie explizit pinnen (siehe erste Antwort).
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Krishty
Establishment
 
Beiträge: 6654
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy

Nächste

Zurück zu Programmiersprachen, Quelltext und Bibliotheken

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste