Question

Je suis référence à une DLL dans mon projet C # comme suit:

[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]

        public static extern void FeeCalculation(string cin, string cout, string flimit,
            string frate, string fwindow, string fincrement, string fbird, 
            string fparameter, string fvalidation, string fcoupon);

La fonction FeeCalculation est exportée comme suit dans la DLL:

extern "C" __declspec(dllexport) void __stdcall FeeCalculation(char *cin, 
char *cout, char *flimit, char *frate,
char *fwindow, char *fincrement, char *fbird,
char *fparameter, char *fvalidation, char *fcoupon);

La fonction DLL renvoie une référence à sa structure interne sous la forme de char * si vous deviez faire référence à cette DLL en C ++, vous procédez comme suit pour faire le calcul et obtenir les structures retournées:

FeeCalculation(buff, (char *)&fans, (char *)fl, (char *)ft, (char *)fw, (char *)fi, (char *)fe, (char *)&fm, (char *)val, (char *)cpn);

Maintenant, comment puis-je récupérer les valeurs renvoyées par référence en utilisant C #? Ce qui signifie, comment dois-je faire la même chose en C # pour obtenir les structures de retour pour obtenir mon calcul retourné? Je sais que je dois créer une méthode dangereuse, mais je ne suis pas clair sur la façon de traiter avec les adresses mémoire en C # comme vous le feriez en C ++.

Modifier: Ci-dessous les États à utiliser IntPtr mais comment situez-vous dans la structure identique pour que les champs de la structure peuvent être référencées

Edit: Voici la structure de retour que je suis intéressé par (Cout):

struct feeAnswer {


    unsigned int    fee;

    unsigned int    tax1;

    unsigned int    tax2;

    unsigned int    tax3;

    unsigned int    tax4;

    unsigned int    surcharge1;

    unsigned int    surcharge2;

    unsigned int    validationFee;

    unsigned int    couponFee1;

    unsigned int    couponFee2;

    unsigned int    couponFee3;

    unsigned int    couponFee4;

    unsigned short int dstay;       //Day Stay

    unsigned short int mstay;       //Minute Stay

};

Voici le (cin) que je passerais ainsi que d'autres structures (ils sont nuls octets au moment, je veux que cela fonctionne d'abord je vais mettre en œuvre le reste):

struct feeRequest {

    unsigned char   day;

    unsigned char   month;

    unsigned int    year;   //2000 ~ 2099



    unsigned char   hour;

    unsigned char   minute;

    unsigned char   rate;

    unsigned char   validation;



    unsigned char   coupon1;

    unsigned char   coupon2;

    unsigned char   coupon3;

    unsigned char   coupon4;

};
Était-ce utile?

La solution

Edit: maintenant que nous avons des structures pour travailler avec, une meilleure solution est possible. Il suffit de déclarer struct en C # qui correspondent à vos struct C ++ de, et de les utiliser dans la déclaration extern

[StructLayout(LayoutKind.Sequential)]
public struct feeAnswer {
   public uint    fee;
   public uint    tax1;
   public uint    tax2;
   public uint    tax3;
   public uint    tax4;
   public uint    surcharge1;
   public uint    surcharge2;
   public uint    validationFee;
   public uint    couponFee1;
   public uint    couponFee2;
   public uint    couponFee3;
   public uint    couponFee4;
   public ushort  dstay;       //Day Stay
   public ushort  mstay;       //Minute Stay
   };

  [StructLayout(LayoutKind.Sequential, Pack=1)]
  public struct feeRequest {
   public byte   day;
   public byte   month;
   public uint   year;   //2000 ~ 2099
   public byte   hour;
   public byte   minute;
   public byte   rate;
   public byte   validation;
   public byte   coupon1;
   public byte   coupon2;
   public byte   coupon3;
   public byte   coupon4;
   };

  [DllImport ("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
             CharSet = CharSet.Ansi)]
  public static extern void FeeCalculation (
          feeRequest cin,
          out feeAnswer cout,
           ...



        ....

réponse originale (avant que nous ayons struct) ci-dessous


Il me semble que ce ne sont pas des références à des chaînes internes, mais plutôt des pointeurs vers des tampons de chaîne qui seront comblées par l'appel. Si vous étiez retournaient pointeurs de chaîne, puis ceux-ci seraient déclarés char** plutôt que char*.

Je pense donc que ce ne sont que des paramètres standard sur. Il y a juste beaucoup d'entre eux. Donc, votre C # Interop ressemblerait à ceci

[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, 
        [MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
        out string cout, 
        [MarshalAs(UnmanagedType.LPStr, SizeConst=100)]
        out string flimit,

ou ceci si vos « chaînes » ne sont pas vraiment des chaînes

[DllImport("FeeCalculation.dll", CallingConvention = CallingConvention.StdCall,
           CharSet = CharSet.Ansi)]
public static extern void FeeCalculation(string cin, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
        out byte[] cout, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst=100)]
        out byte[] flimit,
        ....

Autres conseils

Les paramètres char * dans ce cas ne sont pas des chaînes, mais des pointeurs vers des morceaux d'octets bruts représentant les données. Vous devez rassembler vos paramètres comme les instances du type IntPtr, en collaboration avec Marshal.AllocHGlobal pour créer un morceau de mémoire, puis Marshal.PtrToStructure pour convertir ce bloc de mémoire dans un type .NET utilisable.

Par exemple:

[StructLayout(LayoutKind.Sequential)]
struct MyUnmanagedType
{
    public int Foo;
    public char C;
}

IntPtr memory = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyUnmanagedType)));

try
{
    FeeCalculation(memory);

    MyUnmanagedType result = (MyUnmanagedType)Marshal.PtrToStructure(
        memory, typeof(MyUnmanagedType));
}
finally
{
    Marshal.FreeHGlobal(memory);
}

Pour répondre à votre édition, vous devez créer un struct, puis utilisez la balise StructLayoutAttribute sur les champs afin de rendre l'ordre des octets et le remplissage identique à la dll d'origine a fait.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top