[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.
joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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: 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
Krishty
Establishment
Beiträge: 6790
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
Krishty
Establishment
Beiträge: 6790
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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®

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
Krishty
Establishment
Beiträge: 6790
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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®

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von joggel » 18.10.2016, 16:18

Compiler sagt "nein".

Code: 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
Krishty
Establishment
Beiträge: 6790
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von MasterQ32 » 18.10.2016, 23:35

Klar hat der Meister da was:

Zur Managed-Seite, hier der Part in C#:

Code: 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: 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

biertrinker
Beiträge: 2
Registriert: 24.09.2006, 22:06

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

Beitrag von 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: 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: 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: 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.

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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®

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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: 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von joggel » 02.11.2016, 17:06

That's the plan...
CEO of Dirty Codez Production®

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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: 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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: 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: Alles auswählen

typedef void(*FunctionPointer)(array<OPCDAItemData^>^ arr);
Und hier ...(wie sagt man dazu?) die CallbackFunction-Deklaration

Code: 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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: 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®

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
MasterQ32
Establishment
Beiträge: 1256
Registriert: 07.10.2012, 14:56
Echter Name: Felix Queißner
Wohnort: Stuttgart & Region
Kontaktdaten:

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

Beitrag von 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

joggel
Establishment
Beiträge: 1397
Registriert: 06.11.2007, 19:06

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

Beitrag von 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
Krishty
Establishment
Beiträge: 6790
Registriert: 26.02.2009, 12:18
Benutzertext: state is the enemy
Kontaktdaten:

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

Beitrag von 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

Antworten