簡體   English   中英

C#中的指針從DllImport函數檢索引用

[英]Pointers in C# to Retrieve Reference From DllImport Function

我在C#項目中引用的DLL如下:

[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);

FeeCalculation函數在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);

DLL函數以char *的形式返回對其內部結構的引用,因此,如果要在C ++中引用此DLL,則可以執行以下操作進行計算並獲取返回的結構:

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

現在,如何使用C#檢索通過引用返回的那些值? 意思是,我該如何在C#中執行相同的操作來獲取返回的結構以獲取返回的計算結果? 我知道我需要創建一個不安全的方法,但是我不清楚如何像在C ++中那樣處理C#中的內存地址。

編輯:下面說明要使用IntPtr,但是如何將其放入相同的結構中,以便可以引用結構的字段?

編輯:這是我感興趣的返回結構(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

};

這是我將與其他結構一起傳遞的(cin)(目前它們為零字節,我想先使其工作,然后再實現其余部分):

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;

};

在這種情況下,char *參數不是字符串,而是指向表示數據的原始字節塊的指針。 您應該將參數編組為IntPtr類型的實例,並與Marshal.AllocHGlobal一起創建一個內存塊,然后與Marshal.PtrToStructure一起將該內存塊轉換為可用的.NET類型。

舉個例子:

[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);
}

編輯:現在我們有了可以使用的結構,可能有更好的解決方案。 只需在C#中聲明與您的C ++結構匹配的結構,然后在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,
           ...



        ....

原始答案(在使用結構之前)


在我看來,這些不是對內部字符串的引用,而是對將由調用填充的字符串緩沖區的指針。 如果要返回字符串指針,則將其聲明為char**而不是char*

因此,我認為這些只是標准輸出參數。 只有很多。 所以您的C#互操作看起來像這樣

[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,

或如果您的“字符串”不是真正的字符串

[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,
        ....

要回答您的Edit,您需要創建一個結構,然后在字段上使用StructLayoutAttribute來使字節順序和填充與原始dll相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM