2012-04-30 1 views
2

Je dois passer un tableau d'une structure de C++ à C#. J'ai le code suivant, qui crée d'abord une structure temporaire, puis memcpy à l'adresse de la structure du côté C#. J'ai défini la structure des deux côtés avec le même ordre d'éléments. Lorsque je débogue, je vois que la structure temporaire est remplie correctement, temp_buf (l'adresse de la variable cible) est incrémentée dans la taille de la structure à chaque itération, et memcpy ne renvoie aucune erreur.Passer un tableau de structure de C# à C++

Toutefois, seul le premier élément de la matrice est défini du côté C#.

Voici les définitions du côté C#:

[DllImport(@"MyAwesomeDLL.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "[email protected]@[email protected]@@Z", CharSet = CharSet.Auto)] 
public static extern Int32 GetCoolDevices(out UInt32 p_deviceCount, out Device_s p_devicesBuf); 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
public struct Device_s 
{ 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 51)] 
    public String DeviceName; 
    public UInt32 DeviceID; 
} 

Voici les définitions du côté C:

#pragma pack (1) 
typedef struct 
{ 
    TCHAR device_name [51]; 
    UINT32 device_rid; 
} DEVICE_S; 


int GetDevices (UINT32 *device_count, DEVICE_S *devices_buf) 
{ 
.... 

    while(....) 
    { 
     DEVICE_S tmp_device; 
     memset(&tmp_device, 0, sizeof(DEVICE_S)); 

     tmp_device.device_id = 5; 
     sprintf(tmp_device.device_name, "a string"); 

     DEVICE_S *temp_buf = &(devices_buf[i]); 
     size_t mysize = sizeof(DEVICE_S); 
     memcpy(temp_buf, &tmp_device, mysize); 

     i++; 
     getNextDevice(); 
    } 

..... 
} 

Et, voici comment je l'appelle:

UInt32 MyDecDeviceCnt = 0; 
Device_s[] MyDecDevices = new Device_s[10]; 
int ret = GetCoolDevices(out MyDecDeviceCnt, out MyDecDevices[0]); 

Toute suggestion est appréciée!

+0

@ SamFisher83 - Votre suggestion n'a aucun sens. L'utilisation d'une chaîne est la procédure correcte. Bien sûr, les deux structures n'ont même pas la même taille, la structure C# est au moins de 12 bits plus grande. –

+0

@Ramhound J'ai corrigé mon erreur de faute de frappe. Maintenant, device_name a 51 caractères. Y a-t-il encore une discordance? – mustafa

Répondre

2

L'API que vous avez créée présente un problème. Vous allouez la mémoire pour le tableau du côté géré (10 éléments) mais vous ne passez pas le nombre d'éléments dans le tableau au côté non géré. Le marshaller n'a aucun moyen de déterminer que vous voulez marshaler 10 éléments et le code non managé ne connaît pas la taille du tampon dans lequel il écrit.

Vous pouvez utiliser MarshalAsAttribute.SizeParamIndex pour fournir des informations au marshaller sur la taille de la baie. Jetez également un oeil à l'article Default Marshaling for Arrays. (En particulier les informations sur les tableaux de style C.)

Étant donné la nature de votre API, vous pouvez la modifier pour que la mémoire soit allouée du côté non géré. Vous devrez utiliser un tableau sécurisé ou un hglobal pour permettre à la mémoire d'être libérée du côté géré.

+1

Vous devriez également mentionner 'TCHAR nom_de_l'appareil [20];' vs 'SizeConst = 51' - ceci provoquera' DeviceID' à un mauvais décalage. – ildjarn

+0

J'ai supposé que c'était une simple faute de frappe, mais il doit être corrigé. –

+0

@MartinLiversage - Les chances que cette erreur soit une faute de frappe sont peu probables. –

Questions connexes