C++ Function: Return pointer oder Pointer als Reference
-
Hi,
versuche gerade ne DLL zu schreiben mit VC++2010pro die ich dann unter .Net einbinden will.
In der Dll ist ne Function die mir einen int pointer auf ein int-array als reference zurückgeben soll, oder aber auch ein Pointer als Rückgabewert direkt.
Hab beides versucht klappt aber irgendwie beides nicht.Soweit ich das verstanden hab, wenn ich einem int-pointer das array zuweise enthält der pointer die adresse auf das erste element, und dann sollte mein code eigentlich funktionieren. Kompilieren funzt auch.
Hier mal die Funktion:
__declspec(dllexport) int GetPointerAsRef(char inChar, int *& refint) { int aforward[6] = {1, 2, 3, 4, 5, 6}; int areverse[6] = {6, 5, 4, 3, 2, 1}; int p=0; if(inChar == 'f') { refint=aforward; p=1; } if(inChar == 'r') { refint=areverse; p=1; } return p; }
Und der Aufruf in .Net: (egal ob c# oder vb.net)
Deklaration:
<DllImport("Test.dll")> _ Public Shared Function GetPointerAsRef(ByVal inChar As Char, ByRef myPointer As IntPtr) As Integer End Function
Aufruf:
Dim mypt as IntPtr = Nothing Dim myresult As Integer = GetPointerAsRef("f", mypt)
Fehlermeldung ist dann immer: PInvokeStackImbalance wurde erkannt.
Message: Ein Aufruf an die PInvoke-Funktion GetPointerAsRef hat das Gleichgewicht des Stapels gestört.
Wahrscheinlich stimmt die verwaltete PInvoke-Signatur nicht mit der nicht verwalteten Zielsignatur überein.
Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen.Bin noch ziemlicher Anfänger in c++ vondem her wärs nett wenn mir jemand weiterhelfen könnte.
Thx schonmal
-
Du solltest in den öffentlichen Funktionen keine Referenzen verwenden. C kennt nur Pointer.
Wenn du das Array so definierst wird es am Ende der Funktion zerstört.
Lösungsmöglichkeiten
-
das Array statisch machen
-
das Array global machen in der DLL
-
den benötigten Speicher von aussen übergeben
-
ist wohl die "sauberste" Lösung, allerdings mit etwas Aufwand beim Aufrufer verbunden. Hier muss die C# Anwendung genug Speicher reservieren. Hierzu kannst (musst?) du Marshal.AllocHGlobal() http://msdn.microsoft.com/en-us/library/aa330452(v=vs.71).aspx verwenden
__declspec(dllexport) int GetPointerAsRef(char inChar, int* refint) { static int aforward[6] = {1, 2, 3, 4, 5, 6}; static int areverse[6] = {6, 5, 4, 3, 2, 1}; int p=0; if(inChar == 'f') { refint=aforward; p=1; } if(inChar == 'r') { refint=areverse; p=1; } return p; }
int aforward[6] = {1, 2, 3, 4, 5, 6}; int areverse[6] = {6, 5, 4, 3, 2, 1}; __declspec(dllexport) int GetPointerAsRef(char inChar, int* refint) { int p=0; if(inChar == 'f') { refint=aforward; p=1; } if(inChar == 'r') { refint=areverse; p=1; } return p; }
__declspec(dllexport) int GetPointerAsRef(char inChar, int* refint,size_t refIntSize) { int aforward[6] = {1, 2, 3, 4, 5, 6}; int areverse[6] = {6, 5, 4, 3, 2, 1}; int p=0; if(inChar == 'f') { const size_t size = std::min(refIntSize,6); memcpy(refint,aforward,size); p=1; } if(inChar == 'r') { const size_t size = std::min(refIntSize,6); memcpy(refint,areverse,size); p=1; } return p; }
-