none
win32 dll 讓c#import RRS feed

  • 問題

  • 若要利用vc開發win32 dll 給c#用,是否要用特別寫法呢
    我利用vs2005專案中的 win32 dll建立基本的程式碼讓c#
    引用,但一直出發找不到進入點(Entry)的錯誤,

    .cpp部分
                  #include "stdafx.h"
    #include "testApi.h"
    #ifdef _MANAGED
    #pragma managed(push, off)
    #endif

    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    #ifdef _MANAGED
    #pragma managed(pop)
    #endifTESTAPI_API int ntestApi=0;
    TESTAPI_API int fntestApi(void)
    {
        return 42;
    }CtestApi::CtestApi()
    {
        return;
    }


    .h 部分
    #ifdef TESTAPI_EXPORTS
    #define TESTAPI_API __declspec(dllexport)
    #else
    #define TESTAPI_API __declspec(dllimport)
    #endif

    // 這個類別是從 testApi.dll 匯出的
    class TESTAPI_API CtestApi {
    public:
        CtestApi(void);
        // TODO: 在此加入您的方法。
    };

    extern TESTAPI_API int ntestApi;

    TESTAPI_API int fntestApi(void);

    C#部分
          using System.Runtime.InteropServices;
          [DllImport("testApi.dll")]
          public static extern fntestApi();     //fntestApi 是VC win32 dll範例funtion
         
    註:VC部分純專案建立未加入任何程式碼

    但在程式執行引用fntestApi()時會出現錯誤"找不到testApi.dll中fntestApi進入點"; ==>問題在這

    2006年6月6日 上午 04:05

解答

  • 你現在用的是函數型的 dll ,這個沒聽過可以用物件或是類別。

    若需要作物件,請用 COM DLL 或是 .Net Managed DLL ,不過這種要用參照,不能用 DllImport

    2006年6月7日 上午 05:28

所有回覆

  • C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\Depends.Exe

    看看你的 dll 檔,看看是否是 DllExport 沒宣告好,或是你別名沒宣告好。

    2006年6月6日 上午 09:51
  • 感謝璉兄.昨天查出是因為要被引用的方式或變數前面必須加上extern "C"的問題..

    想在再請一下璉兄l 若我在讓vc中class CtestApi 讓c#能new 此物件要如何做呢?目前只會用參數和funtion的方式
    若要被引用類別有二個部分不知道該怎麼寫

    Q1:
    vc中
    extern "C" 後面不知道加啥和
    2006年6月7日 上午 02:06
  • 你現在用的是函數型的 dll ,這個沒聽過可以用物件或是類別。

    若需要作物件,請用 COM DLL 或是 .Net Managed DLL ,不過這種要用參照,不能用 DllImport

    2006年6月7日 上午 05:28
  • 感謝璉璉兄的回答,我在看了其他人使用後c# call win32 dll發現您說的很正確,
    也是因此在應用層中間又多c# dll,而這支c# dll中才包含
    win32 dll,這樣做確實
    有很多好處,之前小弟觀念是錯誤的,但在c#與vc win32 dll之間的應用,又遇
    到了幾個問題,想在此請教
    一下

    利用函數型的win32 dll,想做byte 與string的形態的處理讓c# 在DllImport後方便處理,

    但在vc 中不知如何使用byte 與string 形態來做處理,再回傳給c#呢?

    2006年6月15日 上午 07:10
  • 這部分我不能給你很肯定的回覆。基本上我是用 VB.NET ,所以純 c 的部份,我只知道概念。

    Bytes 陣列比較單純,當你的 vc 函數 dll 用傳址呼叫時,.Net 再做 dllImport 時會自動封送變數。字串比較麻煩,vc 字串預設是 ANSI 字串,c# 跟 vb.net 都是 Unicode 字串,所以 dllImport 可以設定 charset 。

    DLL 在 Windows 下可分為幾種:

    1. 函數型 dll :Windows 底層的 dll ,所有 Windows API 都是這種,用 dllImport 引用。

    2. COM dll : 可稱 ActiveX DLL ,例如 OWC 、FileObjectSystem 這類。

    3. .Net DLL : 一般用 .Net Managed DLL 稱之並區別,你上面寫用 DLL 包函數型的 DLL 那個 c# 寫的就是 .Net DLL 。

    4. 其它 dll ,可能是 DOS 或資源檔或其他,例如早期 MS C 7.0 裡面除錯器 cv.exe 配的一堆 dll 。

    由於 dll 版本問題,所以基本上同版本呼叫沒問題,跨版本時傳遞要考慮變數型態,基本上 .Net 封送會幫你包好,除非是包含字串的變數或陣列,以下 1 ~ 4 對映上面 1 ~ 4 。

    1. 是最傳統的 dll ,所以基本上是標準變數,頂多加結構這些可以傳遞。

    2. 物件變數需符合 automation 定義,詳情請參考 oleaut32.dll 內的函數說明,這邊已包含 Unicode 字串 (Variant String) 、Double 日期變數、複合陣列 (SafeArray) 等。如果字串無法傳遞,可能要做 ConvertBSTRToString 、ConvertStringToBSTR 等。

    3. 底層變數型態全部重做,原則上 .Net 封送會幫你包好,但是日期、字串、陣列可能會有問題,要測看看才知道。

    4. 除了當資源檔的,大概在 Windows 下都不會用到。

    而 .Net DLL 在設計上是為了解決 DLL 地獄而開發,如果你能使用 .Net DLL 時,基本上不要回去用函數型的 dll ,除非你有很特別的跨語言、編譯器的考量,否則專心使用 .Net DLL 開發你的系統是比較保險的,若是要給 VB6 / IE 用,你可以將你的 .Net DLL 發佈成 COM DLL ,創建型別程式庫。

    2006年6月15日 上午 07:35
  •  璉璉 寫信:

    這部分我不能給你很肯定的回覆。基本上我是用 VB.NET ,所以純 c 的部份,我只知道概念。

    Bytes 陣列比較單純,當你的 vc 函數 dll 用傳址呼叫時,.Net 再做 dllImport 時會自動封送變數。字串比較麻煩,vc 字串預設是 ANSI 字串,c# 跟 vb.net 都是 Unicode 字串,所以 dllImport 可以設定 charset 。

    DLL 在 Windows 下可分為幾種:

    1. 函數型 dll :Windows 底層的 dll ,所有 Windows API 都是這種,用 dllImport 引用。

    2. COM dll : 可稱 ActiveX DLL ,例如 OWC 、FileObjectSystem 這類。

    3. .Net DLL : 一般用 .Net Managed DLL 稱之並區別,你上面寫用 DLL 包涵數型的 DLL 那個 c# 寫的就是 .Net DLL 。

    4. 其它 dll ,可能是 DOS 或資源檔或其他,例如早期 MS C 7.0 裡面除錯器 cv.exe 配的一堆 dll 。

    由於 dll 版本問題,所以基本上同版本呼叫沒問題,跨版本時傳遞要考慮變數型態,基本上 .Net 封送會幫你包好,除非是包含字串的變數或陣列,以下 1 ~ 4 對映上面 1 ~ 4 。

    1. 是最傳統的 dll ,所以基本上是標準變數,頂多加結構這些可以傳遞。

    2. 物件變數需符合 automation 定義,詳情請參考 oleaut32.dll 內的函數說明,這邊已包含 Unicode 字串 (Variant String) 、Double 日期變數、複合陣列 (SafeArray) 等。如果字串無法傳遞,可能要做 ConvertBSTRToString 、ConvertStringToBSTR 等。

    3. 底層變數型態全部重做,原則上 .Net 封送會幫你包好,但是日期、字串、陣列可能會有問題,要測看看才知道。

    4. 除了當資源檔的,大概在 Windows 下都不會用到。

    而 .Net DLL 在設計上是為瞭解決 DLL 地獄而開發,如果你能使用 .Net DLL 時,基本上不要回去用函數型的 dll ,除非你有很特別的跨語言、編譯器的考量,否則專心使用 .Net DLL 開發你的系統是比較保險的,若是要給 VB6 / IE 用,你可以將你的 .Net DLL 發佈成 COM DLL ,創建型別程式庫。



    再次感謝璉兄提供了這麼寶貴的DLL觀念!
    在"怕被反組譯"的考量 之下才想將較關鍵的程式碼利用函數型 dll做包裝,承如
    您所說的利用.Net DLL直接做為開發,不但方便、快速與後續的延伸性充,因
    一直沒有找到較佳的方式保護.Net DLL,才利用win32 dll方式做為包裝。

    byte 的問題,在測試後發現利用vc 中的
    unsigned char 便可解決
    在c#方面,則直接將
    unsigned char形態的字樣改為byte就可以直接
    呼叫(但還未完全精確測試與使用,希望這是正確的方式)。

     題外話:vc 中的CLR所開發的DLL是否也屬於.Net DLL呢?小弟測試了一下利用
     vc的 CLR開發DLL在c#可利用"參考"直接加入,但發現CLR所開發出來的DLL一
     樣會被反組譯Orz..(看來還是用win32的方式寫一”一)

    ps:我利用google查詢的這類的資料,發現大部分討論VC與VB or VC與C#之
     間應用的文章,大多都是來自對岸Orz..
    2006年6月15日 上午 09:57
  • 如果只是怕反組譯...

    .Net 有內建一個社群版的擾亂器,用擾亂器加碼過就可以了。嫌不夠用也可以買協力廠商開發的。

    傳統的 DLL 也是有被反組譯的風險,而且工具還比較多。倒是傳統的 DLL 也可以改名成其他檔名,比如說 xxx.abc ,這樣還是可以用。比較有名的就是印表機的 API 跟 Office 的圖形過濾器。COM/.NET 的我沒試過不同的副檔名。

    CLR 就是 .Net framework 專案,微軟的編譯器也只有 VC 可以做純 Windows 程式、COM、.Net 程式,外掛的編譯器多半可以同時選擇 Windows 或 .Net 程式。

    Mix Language 的基本上國外滿多的,主要是要基於過去的基礎繼續往下開發,所以有很多討論的價值,國內可能沒有比較專門討論的網站,而且很多人喜歡自己重新搞,不過應該還是有人在用,不過國內通常鄙視 VB ,認為這是次一等的語言,所以這類的混合語言討論也不會被重視。

    2006年6月15日 下午 12:04
  • 對了,.Net DLL 還有 License 機制,沒有授權的使用者不能參照該 DLL ,這部份目前我還沒研讀,先前有人討論過,你可以搜尋看看。
    2006年6月15日 下午 12:07
  • 大大請問你怎麼改的...

    能不能send一份sample給我

    我也是找不到進入點ㄟ....

    qazricky@hotmail.com

    2006年7月6日 上午 03:09