Entwickler-Ecke

Basistechnologien - ptruint array von C# nach Delphi zurück nach C#


DerDieter - So 19.11.17 19:11
Titel: ptruint array von C# nach Delphi zurück nach C#
Hallo,

ich habe ein kleines Problem und zwar möchte ich einen ulong array in C# zu einer Delphi DLL übergeben, diese dort mit Werten füllen und wieder zurück zum C# Hauptprogramm geben.
Das ganze funktioniert problemlos für nicht-arrays, hier ein Beispiel was funktioniert:


Delphi-Quelltext
1:
2:
3:
4:
procedure Test(out i: ptruint;) stdcall;
begin
 out := InternalTest(); // InternalTest() gibt einen ptrUint wert zurück.
end;


und in C#:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
 [DllImport("test.dll")]
 public static extern void Test(ref ulong i);

//....
ulong i = 0;
Test(i);
MessageBox.Show(i.ToString());


Das funktioniert einwandfrei.
Aber wenn ich das ganze mit einem Array probiere bekomme ich eine externe Exception:


Delphi-Quelltext
1:
2:
3:
4:
procedure Test(out i: array of ptrUint;) stdcall;
begin
 out[0] := InternalTest();  // InternalTest() gibt einen ptrUint wert zurück.
end;


und in C#:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
 [DllImport("test.dll")]
 public static extern void Test(ref ulong[] i);

//....
ulong[] i = new ulong[3];
Test(i);
MessageBox.Show(i[0].ToString());


Ich habe folgende Varianten auch schon ausprobiert aber das klappt einfach nicht:


C#-Quelltext
1:
2:
3:
4:
5:
 [DllImport("test.dll")]
 public static extern void Test(ref [MarshalAs(UnmanagedType.LPArray] [In, Out]ulong[] i);

[DllImport("test.dll")]
 public static extern void Test(ref [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2] [In, Out] ulong[] i);


Bitte helft mir :(


Th69 - So 19.11.17 20:10

Hallo und :welcome:

ein Array ist schon ein Referenztyp, daher laß mal ref weg:

C#-Quelltext
1:
2:
[DllImport("test.dll")]
public static extern void Test(ulong[] array);

Außerdem noch die Frage: Ist bei dir in Delphi int 64bit groß (denn ein ulong in C# ist es)? Ansonsten auch in C# uint verwenden.


DerDieter - So 19.11.17 21:36

Hallo Th69 und vielen Dank für die Antwort, das klappt super! Und ja ist 64bit groß.

Jetzt habe ich aber das Problem, dass er bei Strings den Dienst verweigert, das Programm stürzt immer ab wenn ich die Dll Funktion aufrufe.
Hier mein Code:


Delphi-Quelltext
1:
2:
3:
4:
procedure Test(out s: array of stringstdcall;
begin
 out[0] := InternalTestStr();  // InternalTestStr() gibt einen string wert zurück.
end;



C#-Quelltext
1:
2:
3:
4:
5:
6:
string[] s = new string[] { """""""""" };
Test(s);
MessageBox.Show(s[0]); 

[DllImport("test.dll")]
 public static extern void Test(string[] s);


Ich habe gelesen das man bei Strings [MarshalAs(UnmanagedType.BStr)] benutzen soll. Aber da meckert der Kompiler und verlangt ByValArray bzw. LpArray (beides hat aber auch nicht funktioniert).


Th69 - Mo 20.11.17 11:19

Hallo,

von welchem genauen Delphi-String sprichst du? Ein shortstring (in Delphi) ist ein spezieller Datentyp, welcher gesondert behandelt werden muß: How can I marshal a Delphi short string using p/invoke? [https://stackoverflow.com/questions/30569111/how-can-i-marshal-a-delphi-short-string-using-p-invoke]
Das ".NET P/Invoke String Marshalling" basiert ja standardmäßig auf nullterminierten Strings (wie in "C").