none
請問如何將C++寫的DLL檔轉成用C#的DLLImport使用? RRS feed

  • 問題

  • 請問各位大大,如何將C++寫的DLL檔轉成用C#的DLLImport使用?
    小弟要取得某裝置的位址,好能操作他,但一直出現錯誤無法取得
    請各位大大協助指導,謝謝


    C++原型 *.h
    DWORD WINAPI FindDeviceListW(LPWSTR *ppszDeviceList);
    #define FindDeviceList FindDeviceListW

    C++原呼叫 *.cpp
    LPTSTR pszDevList[1] = {NULL};
    DWORD dwRet = FindDeviceList(&pszDevList[0]);

    取得後的監示值
    pszDevList[0] 0x00a1a600 L"\\\\?\\usb#vid_c251&pid_2203#7&25aa2865&0&2#{9b199280-fd23-4020-bde9-7015bcb6d61f}" wchar_t *


    C# 部份程式

            [DllImport("Device.dll", EntryPoint = "FindDeviceListW")]
            public static extern int FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]string ppszDeviceList);

            static void Main(string[] args)
            {
                int Text_int;
                String Test_string;

                string[] pszDevList = new string[1] { null };

                Text_int = FindDeviceList(&pszDevList[0]);
            }

    C# 全部程式
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;

    namespace iMD_Test4
    {
        unsafe class Program
        {
            [DllImport("Device.dll", EntryPoint = "FindDeviceListW")]
            public static extern int FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]string ppszDeviceList);

            static void Main(string[] args)
            {
                int Text_int;
                String Test_string;

                string[] pszDevList = new string[1] { null };

                Text_int = FindDeviceList(&pszDevList[0]);
            }
        }
    }

    C# 出現的錯誤
    不能取得Managed類型('string')的 位址 大小 也不能宣告指向它的指標
    引數1:無法從'string' 轉換為 'string'
    2016年3月8日 下午 05:04

解答

  • (1)

    DWORD 對應的應該是 System.UInt32

    (2) 

    public static extern int FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]string ppszDeviceList);

    改成用 ref 傳遞

    public static extern int FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]ref string ppszDeviceList);


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2016年3月9日 下午 06:26
    版主
  • public static extern System.UInt32 FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]ref string ppszDeviceList);

    寫成上面這樣試試 .(就是用 by reference 傳遞參數)


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 Milton6799 2016年3月12日 上午 10:26
    2016年3月10日 上午 02:06
    版主

所有回覆

  • 都用 DllImport 了,為什麼還用 unsafe 模式?

    強力監督SQL Injection問題!!

      • 小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
      • 雲端學堂Facebook: http://www.facebook.com/studyazure

    2016年3月9日 上午 12:03
    版主
  • 朱大大您好~因為原本C++的程式使用指標來存取位址,我並不知道C#要如處理對應才好,所以把指標打開使用

    如果大大您有好做好,麻煩您指導一下,謝謝~(我也試過 ref 但沒成功)

    2016年3月9日 上午 04:36
  • 應該這樣寫就可以了:

    Text_int = FindDeviceList(pszDevList[0]);

    2016年3月9日 上午 05:59
  • 應該這樣寫就可以了:

    Text_int = FindDeviceList(pszDevList[0]);

    請教tihs大大,我過程式在C++原型如下
    C++原型 *.h
    DWORD WINAPI FindDeviceListW(LPWSTR *ppszDeviceList);
    #define FindDeviceList FindDeviceListW

    他的返回參數原來型態為DWORD 我以 C# int 型態對應
    請問有沒有可能對應錯誤?

    我是參考以下網站撰寫
    http://cc-young.blogspot.tw/2012/08/c-cc-dll.html
    謝謝~
    2016年3月9日 上午 11:34
  • 應該這樣寫就可以了:

    Text_int = FindDeviceList(pszDevList[0]);

    tihs大大,我測試結果失敗了~出現

    類型 'System.AccessViolationException' 的未處理例外狀況發生於 iMD_Test4.exe

    其他資訊: 嘗試讀取或寫入受保護的記憶體。這通常表示其他記憶體已損毀。

    2016年3月9日 下午 03:29
  • (1)

    DWORD 對應的應該是 System.UInt32

    (2) 

    public static extern int FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]string ppszDeviceList);

    改成用 ref 傳遞

    public static extern int FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]ref string ppszDeviceList);


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    2016年3月9日 下午 06:26
    版主
  • Bill Chung 大大:請問 LPWSTR 型熊 在C#要如何對應?

    C++原型 *.h
    DWORD WINAPI FindDeviceListW(LPWSTR *ppszDeviceList);

    謝謝~

    2016年3月9日 下午 11:26
  • public static extern System.UInt32 FindDeviceList([MarshalAs(UnmanagedType.LPWStr)]ref string ppszDeviceList);

    寫成上面這樣試試 .(就是用 by reference 傳遞參數)


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 Milton6799 2016年3月12日 上午 10:26
    2016年3月10日 上午 02:06
    版主
  • LPWSTR可以對應成string

    另外如果傳回值的DWORD型態代表的如果是指標的話, 可以對應成IntPtr

    2016年3月10日 上午 04:17
  • Bill Chung 照您的方法可以取到值了,感謝,但有些不同

    C++ 監看值

    pszDevList[0] 0x00a1a600 L"\\\\?\\usb#vid_c251&pid_2203#7&25aa2865&0&2#{9b199280-fd23-4020-bde9-7015bcb6d61f}"   型態:wchar_t *

    C# 監看值

    "\\\\?\\usb#vid_c251&pid_2203#7&25aa2865&0&3#{9b199280-fd23-4020-bde9-7015bcb6d61f}"  型態:string


    C#監看值比C++ 監看值少了 0x00a1a600 L 請問有解嗎?

    我有試過改用StringBuilder一樣會少0x00a1a600 L

    增加 DllImport 參數CharSet = CharSet.Unicode或 CharSet = CharSet.Ansi 也一樣會少0x00a1a600 L

    謝謝~

    2016年3月10日 下午 03:34
  • 各位大大:

    我在想耶,0x00a1a600 L 是不是一種位址的顯示,只出現在C++ IDE環境中,因為他的值會變,但字串的值不變,其實不用管它
    各位大大覺的呢?

    謝謝~

    2016年3月11日 下午 05:02
  • 把監看畫面貼上來看看

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2016年3月11日 下午 05:15
    版主
  • Bill Chung大大:系統說我還沒完成驗証,圖貼不上來,我放在Google雲端硬碟,請您到以下網址查看

    https://drive.google.com/folderview?id=0B9ORcd2U4a0RUGNZSmctWDFjUDg&usp=sharing

    謝謝~

    2016年3月11日 下午 05:29
  • 你應該監看的是 &pszDevList[0] 才對吧 ? 所以 0x00a1a600 L 有可能真的是位址.

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    2016年3月12日 上午 05:22
    版主
  • Bill Chung大大您好,我去看了記憶體位置,比較C++與C#所取得的字串資料是相同的,所以我想這個問題應該是解決了,感謝您的協助~

    我監看記憶體是用以下方式~跟大家分享~感謝 edisonx 大大的文章
    http://edisonx.pixnet.net/blog/post/79372149-%5Bdebug%5D-visual-c%2B%2B-%E8%A8%98%E6%86%B6%E9%AB%94%E7%9B%A3%E7%9C%8B

    謝謝~
    2016年3月12日 上午 10:26
  • 感謝各位大大的解答,謝謝~
    2016年3月12日 上午 10:29