2010-02-15 3 views
3

J'essaye d'appeler une fonction C++ non managée, qui a une structure en tant que paramètre d'entrée. La structure est définie dans le fichier d'en-tête comme ceci:Marshaling un tableau de char de longueur fixe bidimensionnel C++ en tant que membre de structure

struct MyStruct 
{ 
int  siOrder; 
char  aaszNames[6][25]; 
int  siId[6]; 
int  siTones[6];   
}; 

J'ai essayé de déclarer la struct gérée comme suit:

[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 
public struct MyStruct { 

public int siOrder; 

[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst=150)] 
public string aaszNames; 

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=6, ArraySubType=UnmanagedType.I4)] 
public int[] siId; 

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=6, ArraySubType=UnmanagedType.I4)] 
public int[] siTones; 
} 

Mais sans succès. Je devine que le marshaling échoue, puisque le aaszNames est en fait un tableau de six longues chaînes de terminaison nulle. Je essayé de déclarer aaszNames comme

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=150)] 
public char[] aaszNames; 

remplir le tableau avec les valeurs NULL si nécessaire. Mais, encore une fois, rien.

Y a-t-il quelque chose qui me manque? Qu'est-ce que je me trompe? Quelle est la meilleure façon de rassembler cette matrice de caractères 2D?

Des indices, s'il vous plaît.

+1

Ca ne ressemble pas du tout au C++ ... –

+0

Il veut appeler une fonction C++ de C# –

+0

J'ai ajouté une balise C# pour clarifier, je l'espère, ce que l'on veut dire. Je pensais aussi que c'était une pure question C++ jusqu'à ce que j'arrive au code. – Yacoby

Répondre

0
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=150)] 
public char[] aaszNames; 

Ce type de rassemblement a l'air bien. Probablement problème dans l'appel de fonction, ou mauvaise allocation de mémoire/

+0

La fonction que j'appelle, a une structure de plus en tant que paramètre, avec que je n'ai pas de problème. Que voulez-vous dire par mauvaise allocation de mémoire? – TTheot

+0

1. Comment allouer une mémoire à votre structure? 2. Le meilleur moyen pour marshal struct comme paramètre de fonction d'entrée est pointeur (IntPtr). Exemple typique: IntPtr strPtr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (StructType))); Marshal.StructureToPtr (struct, strPtr); Foo (strPtr); Marshal.FreeHGlobal (strPtr); – necrostaz

+0

Je n'attribue vraiment pas de mémoire manuellement. Je suis conscient de cet exemple, mais comme je réussis à passer avec succès l'autre structure (plus simple) comme paramètre d'entrée dans la même fonction, et dans plusieurs autres, je pensais que laisser cela à .NET fonctionnerait aussi. – TTheot

0

J'écrirais un petit c-programme pour vérifier la taille d'octet de la structure C.
Ensuite, je voudrais aller avec l'autre suggestion pour extraire le champ de données par champ. D'un point de vue C, le caractère/0 est traité comme un caractère normal inclus dans les 6 octets alors que C# utiliserait une longueur de 5 et aurait le/0 caché.

-3
char aaszNames[6][25]; 

caractères de C++ est de type 8 bits ~

mais ombles de type C# est Unicode (16 bits)!

si omble chevalier de C++ type < -> octet de C# Type

5

Essayez d'utiliser plusieurs C# struct:

[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Ansi)] 
public struct MyStruct_Name 
{ 
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 25)] 
    public string name; 
} 

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct MyStruct 
{ 
    public int siOrder; 

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6)] 
    public MyStruct_Name aaszNames; 

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I4)] 
    public int[] siId; 

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I4)] 
    public int[] siTones; 
} 

Voilà comment j'ai passais des tableaux de chaînes de style C autour.

N'oubliez pas de créer le contenu de aaszNames! Le marshaller déteste les références nulles.

MyStruct foo = new MyStruct(); 
for (int i = 0; i < 6; i++) 
{ 
    foo.aaszNames[i] = new MyStruct_Name(); 
    foo.aaszNames[i].name = ""; 
} 

Bonne chance!

Questions connexes