2010-10-04 5 views
0

Nous avons le code suivant entre C# et c dll. Cependant, lors de l'impression de la valeur dans la fonction C dll, les valeurs associées aux propriétés du double tableau sont toutes 0,0000000. J'ai mis quelques commentaires en ligne pour le code ayant des problèmes. Avons-nous oublié quelque chose pour configurer le comportement de rassemblement?Passage d'un tableau C# de structures avec un tableau de double membre en C par référence

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
namespace ConsoleApplication 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MonteCarlo montecarlo = new MonteCarlo(); 
      montecarlo.RunMonteCarlo(); 
     } 
    } 
    class MonteCarlo 
    { 

     [DllImport("MonteCarloCUDA.dll")] 
     public static extern int MonteCarloPrint([In, Out]PurchaseOrder[] purchaseorders, int length); 

     public void RunMonteCarlo() 
     { 

      PurchaseOrder[] purchaseorders = new PurchaseOrder[3]; 

      purchaseorders[0] = new PurchaseOrder(); 
      purchaseorders[0].Value1 = "AAAAA"; 
      purchaseorders[0].Value2 = 0.111; 
      purchaseorders[0].Value3 = new double[2]; // Assign the values to array of double 
      purchaseorders[0].Value3[0] = 0.11111; 
      purchaseorders[0].Value3[1] = 0.22222; 

      purchaseorders[1] = new PurchaseOrder(); 
      purchaseorders[1].Value1 = "BBB"; 
      purchaseorders[1].Value2 = 0.222; 
      purchaseorders[1].Value3 = new double[2]; 
      purchaseorders[1].Value3[0] = 0.33333; 
      purchaseorders[1].Value3[1] = 0.44444; 

      purchaseorders[2] = new PurchaseOrder(); 
      purchaseorders[2].Value1 = "CCC"; 
      purchaseorders[2].Value2 = 0.333; 
      purchaseorders[2].Value3 = new double[2]; 
      purchaseorders[2].Value3[0] = 0.55555; 
      purchaseorders[2].Value3[1] = 0.66666; 

      int result = MonteCarloPrint(purchaseorders, purchaseorders.Length); 

      Console.ReadKey(); 
     } 

     [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] 
     public unsafe struct PurchaseOrder 
     { 
      public string Value1; 

      public double Value2; 

      public double[] Value3; // Array of double member 
     } 
    } 
} 

// C Code de

#include <stdio.h> 

typedef struct PurchaseOrder 
{ 
    char* Value1; 
    double Value2; 
    double* Value3; 
}; 



__declspec(dllexport) int __stdcall MonteCarloPrint(PurchaseOrder *hostPurchaseOrders, int length) 
{  
    printf("\nSize of PurchaseOrder: %d",sizeof(PurchaseOrder)); 

    for (int i = 0; i < length; i++) 
    {   
     printf("\n\nAddress: %u",hostPurchaseOrders+i);   
     printf("\nValue1: %s",(hostPurchaseOrders+i)->Value1); 
     printf("\nValue2: %f",(hostPurchaseOrders+i)->Value2); 
     printf("\nValue3[0]: %f",(hostPurchaseOrders+i)->Value3[0]); 
     printf("\nValue3[1]: %f",(hostPurchaseOrders+i)->Value3[1]); 

    } 
}} 

Le résultat d'impression de la fonction dll C

 
Size of PurchaseOrder: 24 

Address: 13180880 
Value1: AAAAA 
Value2: 0.111000 
Value3[0]: 0.000000 // No value are marshalled 
Value3[1]: 0.000000 

Address: 13180904 
Value1: BBB 
Value2: 0.222000 
Value3[0]: 0.000000 
Value3[1]: 0.000000 

Address: 13180928 
Value1: CCC 
Value2: 0.333000 
Value3[0]: 0.000000 
Value3[1]: 0.000000 
+0

Stratford, il y a eu plusieurs tentatives pour améliorer la mise en forme de votre code source. Ne le défait pas. Obfusciter votre code ne vous permet pas d'obtenir de meilleures réponses. – dtb

Répondre

1

Retirez la propriété du pack de la déclaration [DllImport], il est faux. Vous n'utilisez pas une directive #pragma pack dans votre code C, la valeur par défaut de Pack est appropriée. Si cela aurait été en vigueur alors votre code C aurait rapporté 16.

Vous voyez 24 parce qu'il y a 4 octets de rembourrage pour aligner le double et 4 octets de rembourrage à l'extrémité de la structure pour faire le double alignement lorsque la structure est utilisée dans un tableau. 4 + 4 + 8 + 4 + 4 = 24. L'emballage en vigueur est 8, la valeur par défaut.

Vous pouvez le rendre plus efficace en échangeant Value2 et Value3 pour obtenir une structure de 16 octets, aucun rembourrage n'est nécessaire. Au cas où cela C'est ce que fait le compilateur JIT.


Le problème suivant est plus difficile, le P/Invoke placier mobilisera l'ensemble intégré comme SAFEARRAY. Vous pouvez résoudre que du côté non géré en utilisant ce code:

#include "stdafx.h" 
#include <stdio.h> 
#include <objidl.h> 

struct PurchaseOrder 
{ 
    char* Value1; 
    double Value2; 
    LPSAFEARRAY Value3; 
    int fence; 
}; 


extern "C" 
__declspec(dllexport) int __stdcall MonteCarloPrint(PurchaseOrder *hostPurchaseOrders, int length) 
{  
    printf("\nSize of PurchaseOrder: %d",sizeof(PurchaseOrder)); 

    for (int i = 0; i < length; i++) 
    {   
     printf("\n\nAddress: %u",hostPurchaseOrders+i);   
     printf("\nValue1: %s",(hostPurchaseOrders+i)->Value1); 
     printf("\nValue2: %f",(hostPurchaseOrders+i)->Value2); 
     double* arrayPtr; 
     if (S_OK == SafeArrayAccessData((hostPurchaseOrders+i)->Value3, (void**)&arrayPtr)) { 
      printf("\nValue3[0]: %f", arrayPtr[0]); 
      printf("\nValue3[1]: %f", arrayPtr[1]); 
     } 
    } 
    return 0; 
} 

J'ai écrit le code en utilisant le compilateur C++, vous devrez peut-être modifier.

+0

Salut Hans, j'ai enlevé le pack = 1 de [StructLayout (LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] mais le problème existe toujours. Les vlaue3 sont peuplés par 0.00000 et la taille de purchaseorder est 24. – Stratford

+0

@Stratford - post mis à jour. –

Questions connexes