Dann verdränge ich den Gedanken mal ganz schnell wieder aus meinem Kopf, und aus meinem Code …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.
if (mCallback == NULL)
{
mCallback = new MyCallBack();
mCallback->setCallBack(funcPtr); // <= hier übergebe ich ja den Funktionspointer der Klasse MyCallback.
}
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);
}
typedef void(*FunctionPointer)(array<OPCDAItemData^>^ arr);
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));
}
};
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());
}
};
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);
}
};
MSDN hat geschrieben:Ruft das Objekt ab, das von diesem Handle dargestellt wird, oder legt dieses fest.
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.
VC hat geschrieben:ein Member einer nicht-verwaltet-Klasse kann kein Handle sein
Fehler LNK2038 Konflikt ermittelt f³r "RuntimeLibrary": Der Wert "MT_StaticRelease" stimmt nicht mit dem Wert "MD_DynamicRelease"
Zurück zu Programmiersprachen, Quelltext und Bibliotheken
Mitglieder in diesem Forum: Majestic-12 [Bot] und 1 Gast