none
C# import dll 遇到回傳值型態為float* RRS feed

  • 問題

  • 各位大大好:
          之前有使用過dll import,都沒有遇到什麼大問題,但是這回遇到dll裡面的函式長這樣,我就困惑了。
    float *getTest(int* data, int dataSize, float oldXX, float oldStatus, float recordIdx, int isDataSet);
    參數說明如下:
    輸入:
    data : 資料陣列
    dataSize : 陣列大小(預設是3072)
    oldXX : 上一筆回傳的float[0]
    oldStatus : 上一筆回傳的float[1]
    recordIdx : 第一筆是 0 ,其他是 1
    isDataSet : debug的.直接傳入 1 。

    輸出:
    return 一個 float [8] 的陣列

    主要遇到幾個問題,也搜尋過爬過文,還是解決不了,只好來發問,
    1.出現『找不到 PInvoke DLL 'test.dll'。』→dll確定有放在專案之下,且debug下也放了
    2.InvalidProgramException→發生的原因應該跟我嘗試要產生float*有關
    附上我目前卡關的code
     [DllImport("test.dll", EntryPoint = "getTest", SetLastError = true)]

    unsafe public extern static float* getTest(int* data, int dataSize, float oldXX, float oldStatus, float recordIdx, int isDataSet);

    public Form1()
    {

    InitializeComponent();

    unsafe

    {

    int* data;

    int x=1011;

    data = &x;



    // float* esAry = stackalloc float[8]; //這個開了會出現2的錯誤

    float* esAry = (float*)getTest(data, 1, 0, 0, 0, 1);

    }
    因為小妹我對於指標不是很熟悉,所以也不清楚是不是自己的問題還是有什麼其他地方沒注意到,先謝謝各位了。


    Update:
    1/28取得改版後的dll,函式修正為
    char *getTest(char *data, int dataSize, float oldXX, float oldStatus, float recordIdx, int isDataSet);
    於是我寫法改為
      [DllImport("test.dll", EntryPoint = "getTest")]
            public extern static string getTest(string data, int dataSize, Single oldXX, Single oldStatus, Single recordIdx, int isDataSet);
            public Form1()
            {
                InitializeComponent();
                
                string str =  getTest("1,2,3,4,5,6,7,8,9,10", 3072, 0, 0, 0, 1);
            }
    結果還是出現『找不到 PInvoke DLL 'test.dll'。』的訊息。><
    再麻煩大大指引方向,謝謝

    • 已編輯 piyolala 2010年1月28日 上午 06:41
    2010年1月27日 上午 08:19

解答

所有回覆

  • 您的第一個問題提到 [dll確定有放在專案之下,且debug下也放了] 有嘗試將 dll 加入參考嗎?

    參考看看這篇 [Windows Mobile]加入與註冊 DLL

    我的Blog .NET菜鳥自救會
    2010年1月27日 上午 08:38
    版主
  • 
    
     [DllImport("test.dll", EntryPoint = "getTest", SetLastError = true)]
    
             extern static float[] getTest(int[] data, int dataSize, float oldXX, float oldStatus, float recordIdx, int isDataSet);
    
     float[] esAry = getTest(data, 1, 0, 0, 0, 1);

    Marshalling Types During Platform Invoke (P/Invoke) on the Microsoft .NET Compact Framework
    http://msdn.microsoft.com/en-us/library/aa446538.aspx

    可以用陣列嗎...

    2010年1月27日 上午 08:46
  • 小歐大大,我有嘗試加入參考,不過會出現『無法加入'test.cll'的參考』的警告視窗,所以我是用加入現有項目的方法加入的。
    2010年1月27日 上午 09:21
  • Joe大大,其實我也很困擾是不是能用陣列。
    我之前是參考小朱大大分享的
    http://msdn.microsoft.com/zh-tw/library/ac7ay120%28VS.80%29.aspx
    去搜尋float*的對應型態,不過沒有找到。
    2010年1月27日 上午 09:24
  • 小歐大大,我有嘗試加入參考,不過會出現『無法加入'test.cll'的參考』的警告視窗,所以我是用加入現有項目的方法加入的。

    Hi! 詢問一下,您的 test.dll 的來源,以及是否可使用於 智慧型裝置專案 ?
    我的Blog .NET菜鳥自救會
    2010年1月27日 上午 09:33
    版主
  • 小歐大~dll來源是另一位專案相關的工程師使用C開發並自行編譯後給我的。能否使用於智慧型裝置專案這個我們都不清楚耶~因為我原先的觀念是C#可以import c開發的dll進來,然後C#就可以呼叫函式來使用。(後來發現我的觀念好像有很大的錯誤><) 如果要使用於智慧型專案在編譯過程是不是有哪邊要注意呢?謝謝
    2010年1月27日 上午 09:39
  • 回傳值若是array的話,要用System.IntPtr接,
    再搭配BitConverter做轉型

    如果dll檔還能改的話,建議把float array改成參數傳進去
    在dll中直接賦值,這樣會簡單很多

    2010年1月27日 上午 10:33
  • 謝謝Zion大大。您提到用System.IntPtr接,是在import下面宣告的地方修改嗎?像下面那樣嗎?還有搭配BitConverter做轉型的部份可以提供code讓我參考嗎?謝謝
    unsafe public extern static IntPtr getTest(int* data, int dataSize, float oldXX, float oldStatus, float recordIdx, int isDataSet);

    『把float array改成參數傳進去』→這是指reference寫法嗎?這個做法我有考慮過,不過目前負責dll的工程師很忙沒有時間修改,我可能還是得自己先試試看。


    補充一下,我剛試另一個方法,沒有出現找不到dll的訊息了,倒是在呼叫getTest函式那行出現NotSupportedException這樣的訊息,不過不知道這樣算不算成功一半@@
    [DllImport("test.dll", EntryPoint = "getTest")]
    unsafe public static extern float[] getTest([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.R4, SizeParamIndex = 0)] int* data, int dataSize, float oldHR, float oldStatus, float recordIdx, int isDataSet);
    public Form1()
    {
    InitializeComponent();
    unsafe
    {
    int* data;
    int x = 1024;
    data = &x;
    //float* esAry = stackalloc float[8];
    float[] esAry = new float[8];
    esAry = getTest(data, 1, 0, 0, 0, 1);
    }
    2010年1月27日 上午 10:46
  • 謝謝Zion大大,那兩篇很有幫助。
    我想要補充問一下各位大大,我要怎麼用C#的code create 出int*的array呢?
    目前參考上面兩篇後執行會出現NotSupportedException的訊息,我懷疑是我傳入的data不是array的關係@@
    2010年1月27日 下午 05:26
  • Update:
    1/28取得改版後的dll,函式修正為
    char *getTest(char *data, int dataSize, float oldXX, float oldStatus, float recordIdx, int isDataSet);
    於是我寫法改為
     [DllImport("test.dll", EntryPoint = "getTest")]
        public extern static string getTest(string data, int dataSize, Single oldXX, Single oldStatus, Single recordIdx, int isDataSet);
        public Form1() {
         InitializeComponent();
         string str = getTest("1,2,3,4,5,6,7,8,9,10", 3072, 0, 0, 0, 1);
        }
    結果還是出現『找不到 PInvoke DLL 'test.dll'。』的訊息。>< 再麻煩大大指引方向,謝謝
    各位大大,我大概知道原因了,因為我用相同的code在windows form的專案上跑,是OK的;手機裝置卻是有問題的。 我用Depend.exe去看test.dll,看到裡面有引用kernel32.dll,我想要問如果要讓手機裝置可以使用該dll是不是表示要引用coredll.dll呢?有沒有人可以分享如何將開發好的C code編譯成手機裝置能使用的dll呢?
    2010年1月28日 上午 08:14
  • Hi,
    要開發Mobile相關的應用程式,要安裝相關的SDK,裝完SDK之後才會有相關的檔案,像是include擋,lib檔案等等

    例如這個(請依照你實際的目標平台)
    Windows Mobile 6 Professional and Standard Software Development Kits Refresh
    請注意討論區相關規則,良好的討論環境需要大家共同努力、遵守
    2010年1月28日 上午 08:38
    版主
  • bauann大大,我是負責開發Mobile相關的應用程式,我也都有安裝SDK了,意思是我要將lib打包給開發dll的工程師去做編譯嗎?謝謝
    2010年1月28日 上午 08:46
  • bauann大大,我是負責開發Mobile相關的應用程式,我也都有安裝SDK了,意思是我要將lib打包給開發dll的工程師去做編譯嗎?謝謝
    是開發dll的環境得安裝mobile相關的sdk,並且得設定專案是要在mobile裝置上執行。

    2010年1月28日 上午 09:25
  • 是開發dll的環境得安裝mobile相關的sdk,並且得設定專案是要在mobile裝置上執行。
    Zion大大,可是用純C開發的環境還可以安裝相關SDK嗎?還是一定得用VS2008開發呢?感謝~
    2010年1月28日 上午 09:36
  • 是開發dll的環境得安裝mobile相關的sdk,並且得設定專案是要在mobile裝置上執行。
    Zion大大,可是用純C開發的環境還可以安裝相關SDK嗎?還是一定得用VS2008開發呢?感謝~

    抱歉,沒說的很清楚,如Zion大所提,開發DLL的工程師那邊也要裝SDK,這樣才會有相關的檔案可以用,像是一些.h或是.lib的東西。
    請注意討論區相關規則,良好的討論環境需要大家共同努力、遵守
    2010年1月28日 上午 11:46
    版主
  • 感謝~bauann大大,我會再告知開發dll的工程師,如果ok會再來回報的,也謝謝zion大大。
    2010年1月28日 下午 03:26