none
請教關於keyword dynamic的使用 RRS feed

  • 問題

  • OS: XPP SP3

    IDE: VS2010 Professional

    我有個原生的dll,其中有個函式如下

     

    bool ImageGetData ( void * pData, int& numElements, int dataType = 0 ) 
    

    參數如下:

    pData: pointer to data

    numElements: number of data elements on input, number of copied elements on output

    dataType: 0 = double, 1 = float

    正常情況下,用DllImport包起來

     

    [DllImport(DllName, CharSet = CharSet.Unicode, EntryPoint = "#38")]
    static extern public bool ImageGetData(double[] pData, ref int numElements, int dataType = 0);
    

     

    一般使用狀況下,若都是使用dataType = 0的狀況都沒問題。

    但若使用dataType為1時,傳回的資料就不對。

    所以有個想法,不知道能不能利用dynamic來達到不管是dataType是0還是1都能正常運作。

    試了一下的寫法,編譯沒問題,但執行時會出現"記憶體損毀的例外"

    不知道前輩們有什麼解法?謝謝

    以下是我的想法

    dynamic pData;
    int dataType = 0;
    if(dataType == 0)
      pData = new double[numElement];
    else
      pData = new float[numElement];
    
    ImageGetData(pData, ref numElement, dataType);
    
    [DllImport(DllName, CharSet = CharSet.Unicode, EntryPoint = "#38")]
    static extern public bool ImageGetData(dynamic pData, ref int numElements, int dataType = 0);

     

    希望是不管任何dataType都能使用。謝謝


    • 已編輯 Howard_cmit 2011年4月14日 上午 06:49 格式錯亂
    2011年4月14日 上午 06:46

解答

  • >>IntPtr pData
    這表示你廠商dll本身就有處理此需求

    顧妳可以自行封裝一下,透過重載即可

    public bool ImageGetData(double[] pData)
    {
    int num = pData.Count;
    return ImageGetData(pData,  num, 0);
    }

    public bool ImageGetData(float[] pData)
    {
    int num = pData.Count;
    return ImageGetData(pData, num, 1);
    }

    上面的寫法必須確認廠商的IntPtr是否結構上跟.net的double與float相同,如不是,你必須在上面兩個函式處理此問題.

    • 已標示為解答 Howard_cmit 2011年4月14日 上午 08:05
    2011年4月14日 上午 07:42

所有回覆

  • 修改你的Win32 Dll改採byte陣列,然後在C#中將pData改用byte[]作為傳入參數型態,在你的Win32 dll中處理此資料型態轉換問題即可.

    2011年4月14日 上午 07:03
  • 不好意思,沒說清楚,該DLL是廠商提供的,我無法修改。

    試到一種方法可行,不過總覺得不是最好的解法

    希望還有其寫廨法。謝謝

     

         dynamic pData;
         int dataType = 0;
         if (0 == dataType)
          pData = new double[numElement];
         else
          pData = new float[numElement];
         GCHandle gcHandle = GCHandle.Alloc(pData, GCHandleType.Pinned);
         IntPtr ptrData = gcHandle.AddrOfPinnedObject();
         ImageGetData(ptrData, ref numElement, dataType);
    
    [DllImport(DllName, CharSet = CharSet.Unicode, EntryPoint = "#38")]
      static extern public bool ImageGetData(IntPtr pData, ref int numElements, int dataType = 0);

    2011年4月14日 上午 07:35
  • >>IntPtr pData
    這表示你廠商dll本身就有處理此需求

    顧妳可以自行封裝一下,透過重載即可

    public bool ImageGetData(double[] pData)
    {
    int num = pData.Count;
    return ImageGetData(pData,  num, 0);
    }

    public bool ImageGetData(float[] pData)
    {
    int num = pData.Count;
    return ImageGetData(pData, num, 1);
    }

    上面的寫法必須確認廠商的IntPtr是否結構上跟.net的double與float相同,如不是,你必須在上面兩個函式處理此問題.

    • 已標示為解答 Howard_cmit 2011年4月14日 上午 08:05
    2011年4月14日 上午 07:42
  • 謝謝programlin

    之前也有想到用您說的方式,只是剛好想說.Net4有dynamic這東東

    所以才想試試。


    另外結合programlin的想法,實際上只有包兩次就行了

    例如:

    [DllImport(DllName, CharSet = CharSet.Unicode, EntryPoint = "#38")]
      static extern public bool ImageGetData(double[] pData, ref int numElements, int dataType = 0);
      [DllImport(DllName, CharSet = CharSet.Unicode, EntryPoint = "#38")]
      static extern public bool ImageGetData(float[] pData, ref int numElements, int dataType = 1);
    這樣子也是可以的。

    2011年4月14日 上午 08:07
  • MSDN Magazine剛好上個月有篇專欄詳細的介紹在.net中的動態型別.
    你可以參閱
    http://msdn.microsoft.com/en-us/magazine/gg598922.aspx

     

    2011年4月15日 上午 03:02