struct-Array an C++-DLL übergeben
-
sothis_ schrieb:
Konrad Rudolph schrieb:
sothis_ schrieb:
ich hatte mal ein ähnliches problem, finde den code aber leider nicht mehr. ich kann mich wage erinnern einen struktur prototypen als class in c# deklariert zu haben, welche das selbe layout wie die c struktur besaß (besitzte? :s). an die importierte c funktion habe ich dann einen IntPtr auf eine instanz dieser klasse übergeben.
Das könnte sogar funktionieren, wenn man aufpasst, es ist aber riskant, und codelastig. Man muss sich nämlich einen pinned-Pointer besorgen, damit der GC nicht anfängt, die Klasse plötzlich woanders hinzuräumen. Außerdem ist es mit Kanonen auf Spatzen, denn hier soll ja mit Arrays gehandelt werden.
in erster linie ging es doch um strukturen?
Ja. Und? Zusammenhang?
iirc hatte ich die lösung auch irgendwo von einem microsoft forum und schien die 'richtige' zu sein wenn man zeiger/referentzen auf structs zwischen managed und unmanaged code übergibt.
Das kann ich mir nicht vorstellen, denn genau dafür ist ja das (automatische!) Marshalling zwischen Managed und Unmanaged Code da.
edit: oh, und was meinst du mit codelastig? viel zu schreiben war es jedenfalls nicht
Na doch, da Du ja eine unsafe-Methode hast, in der Du zuerst den Zeiger pinnen musst, hast Du auf jeden Fall mehr zu schreiben (= mehr Möglichkeiten, Fehler zu machen) als wenn Du die Methode direkt aufrufst.
-
Sollte man nicht auch immer diese "layout sequential" Property bei der Struktur mit angeben wenn man die mit PInvoke verwenden will?
-
hustbaer schrieb:
Sollte man nicht auch immer diese "layout sequential" Property bei der Struktur mit angeben wenn man die mit PInvoke verwenden will?
Ja, das ist in der Tat sauberer, hat aber mit dem Problem nichts zu tun, da ab Visual Studio 2005 (bzw. der damit verbundenen Version der Compiler) das Sequential-Layout die Standardeinstellung ist.
-
Konrad Rudolph schrieb:
hustbaer schrieb:
Sollte man nicht auch immer diese "layout sequential" Property bei der Struktur mit angeben wenn man die mit PInvoke verwenden will?
Ja, das ist in der Tat sauberer, hat aber mit dem Problem nichts zu tun, da ab Visual Studio 2005 (bzw. der damit verbundenen Version der Compiler) das Sequential-Layout die Standardeinstellung ist.
Ich nutze noch das VS2005. Also könnte das was mit dem Problem zu tun haben?
-
Nö daran wirds nicht liegen wenn das sowieso ab 2005 Standard ist (wusste ich nicht, obwohl ich 2005 verwende
).
Wenn du in/out brauchst kann ich dir leider auch nicht helfen.
-
hustbaer schrieb:
Nö daran wirds nicht liegen wenn das sowieso ab 2005 Standard ist (wusste ich nicht, obwohl ich 2005 verwende
).
Wenn du in/out brauchst kann ich dir leider auch nicht helfen.Jetzt macht meine Frage auch keinen Sinn mehr. Gestern stand bei Konrad Rudolphs Post auch noch 2008...
-
_matze schrieb:
hustbaer schrieb:
Nö daran wirds nicht liegen wenn das sowieso ab 2005 Standard ist (wusste ich nicht, obwohl ich 2005 verwende
).
Wenn du in/out brauchst kann ich dir leider auch nicht helfen.Jetzt macht meine Frage auch keinen Sinn mehr. Gestern stand bei Konrad Rudolphs Post auch noch 2008...
Sorry, das ist richtig. Ich hatte den Fehler in meinem Posting gleich bemerkt und editiert, daher habe ich mir den „Edit“-Hinweis geschenkt. Du bist mit Deiner Frage anscheinend genau so dazwischengekommen, dass Du noch die falsche Zahl gelesen hast, aber schon die richtige zitiert.
-
Hallo,
ich grab diesen Thread nochmal aus. Vielleicht könnte Matze ja mal schreiben wie er es letztendlich umgesetzt hat.
Ich bin nämlich gerade an dem gleichen Problem. Bei einer Übergabe des Struktur-Arrays kann ich im C-Programm zwar lesen, aber nicht schreiben.Zum Testen habe ich mir jetzt folgendes geschrieben:
struct myStruct { int val; char data[20]; }; int printMyStructArray(struct myStruct myStr[], int anz){ int i; myStr[1].val = 987; //TEST schreiben for (i = 0; i < anz; i++) { printf("\nmyStruct[%d].val = %d\n", i, myStr[i].val); printf("myStruct[%d].data = %s\n", i, myStr[i].data); } return anz; }
Das Ganze in eine DLL gepackt und im C#-Programm folgende Importbeschreibung:
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private struct myStruct { public Int32 val; [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 20)] public string data; } // int printMyStructArray(struct myStruct myStr[], int anz); [DllImport("mingw_dll.dll")] private static extern int printMyStructArray( myStruct[] myStr, int anz );
Und zum ausprobieren folgendes:
myStruct[] myStr = new myStruct[20]; myStr[0].val = 12; myStr[0].data = "Dies"; myStr[1].val = 34; myStr[1].data = "ist"; myStr[2].val = 56; myStr[2].data = "ein"; myStr[3].val = 78; myStr[3].data = "Test"; Console.WriteLine("Vorher:"); Console.WriteLine("myStr[1].val = " + myStr[1].val); ret = printMyStructArray(myStr, 4); Console.WriteLine("Nachher:"); Console.WriteLine("myStr[1].val = " + myStr[1].val); Console.WriteLine("returned: " + ret);
Ausgabe des Programmes:
Vorher: myStr[1].val = 34 myStruct[0].val = 12 myStruct[0].data = Dies myStruct[1].val = 987 myStruct[1].data = ist myStruct[2].val = 56 myStruct[2].data = ein myStruct[3].val = 78 myStruct[3].data = Test Nachher: myStr[1].val = 34 returned: 4
Das Lesen geht also, nur das Schreiben nicht.
Oben wurde ja mal geschrieben dass man das Problem lösen kann indem man die Struktur in eine extra Klasse packt. Gibt es dazu vielleicht ein Beispiel, oder eine andere Lösung?
Gruß
Thomas
-
Für mein konkretes Testbeispiel konnte ich das Problem mittels des Out-Attributes lösen:
[DllImport("mingw_dll.dll")] private static extern int printMyStructArray([In, Out] myStruct[] myStr, int anz);
Link zur MSDN:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.outattribute.aspxGruß
-
Hi,
ich hatte genau das gleiche Problem, vielen Dank fuer die [In,Out] Loesung !!!
Funktioniert !