Laden...

[gelöst] Marshaling einer Struct mit String und embedded Array

Erstellt von Spook vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.142 Views
S
Spook Themenstarter:in
248 Beiträge seit 2008
vor 15 Jahren
[gelöst] Marshaling einer Struct mit String und embedded Array

Hallo zusammen,

ich möchte eine C-Struct in C# verwenden. Bisher hat dies auch immer ohne Probleme geklappt jedoch ist es diesmal die erste Struct, die ein embedded Array beinhaltet.
Die Struct sieht folgendermaßen aus (Beispiel):

typedef struct
{
	int	ID;
	char*	Name;
	double	Data[6];
	int	Reserved;
} TestStruct;

Die Struct wird mit folgender Beispielfunktion gefüllt:

void* DLL_EXPORT GetData(TestStruct* ptr)
{
	int i;

	if (ptr)
	{
		ptr->ID = 1;
		ptr->Name = "Dies ist ein Teststring";
		for(i=0;i<6;i++)
			ptr->Data[i]=(double)(i+100);
		ptr->Reserved = -1;
	}

	return ptr;
}

In C# habe ich diese so eingebunden:

[DllImport("library.dll")]
public static extern IntPtr GetData(out TestStruct t);

Wenn ich nun die Struct wie folgt in C# deklariere, wird der String automatisch gemarshalt, so wie man es erwartet. Die beiden Ints sind ebenfalls gesetzt. Jedoch wird im embedded Array nur der erste Eintrag gesetzt, die anderen sind 0.

	unsafe struct TestStruct
	{
		int ID;
		string Name;
		fixed double Data[6];
		int Reserved;
	}

Deklariere ich die Struct um, so dass der String nicht gemarshalt werden muss, wird das embedded Array normal gefüllt:

	unsafe struct TestStruct
	{
		int ID;
		char* Name;
		fixed double Data[6];
		int Reserved;
	}

Wie es scheint, wird das embedded Array nicht korrekt kopiert, sobald der Marshaler eine Kopie der Struct erstellen muss (was er für den String in der ersten Implementierungsvariante muss).

Kennt jemand eine Möglichkeit den char-Pointer elegant als String zu marshalen und gleichzeitig ein embedded Array zu nehmen?

Spooky

3.511 Beiträge seit 2005
vor 15 Jahren

Das unsafe braucht man in ca. 99% aller Fälle nicht 🙂

Probiere mal


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct TestStruct
{
  public int ID;
  [MarshalAs(UnmanagedType.LPWStr)]
  public string Name;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
  public double[] Data;
  public int Reserved;
}

Müsstest du ggf. anpassen, wenn es sich nicht um Unicode Strings handelt.

"Jedes Ding hat drei Seiten, eine positive, eine negative und eine komische." (Karl Valentin)

S
Spook Themenstarter:in
248 Beiträge seit 2008
vor 15 Jahren

Hallo Khalid,

vielen Dank für die Lösung.
Jedoch frage ich mich, warum er beide Fälle seperat marshalen kann, zusammen aber nicht.

Spooky