Windows Mobile和Wince(Windows Embedded CE)下如何封裝Native DLL提供給.NET Compact Framework進行調用

來源:互聯網
上載者:User
背景

在Windows Mobile和Wince(Windows Embedded CE)產品開發中,有時候會使用C++封裝一些共用代碼,例如在我們項目中使用了C++封裝了一個對USB通訊的公開程式碼程式庫,這些共用代碼編譯成靜態庫,其他模式使用的時候,只需要include標頭檔,連結lib庫就可以了,但是.NET Compact Framework的程式沒有辦法使用C++編譯的靜態庫,所以產生封裝Native DLL提供給.NET Compact Framework程式調用的需求。

 

簡介

本文講述在Windows Mobile和Wince(Windows Embedded CE)下如何封裝Native DLL提供給.NET Compact Framework進行調用。

 

可選方案

在.NET framework下可以把C++編譯成託管的DLL,這樣.NET的程式可以直接調用這個DLL了,但是在.NET Compact Framework下,不支援managed c++,所以只能封裝成Native的DLL,然後.NET Compact Framework P/Invoke該Native DLL。 封裝Native的DLL有兩個可選的方案。

 

方案一: .DEF檔案

使用.DEF檔案,.DEF檔案可以定義輸出介面

LIBRARY   NativeLib
EXPORTS
Insert @1
Delete @2
Member @3
Min @4

上面的.def檔案定義了四個輸出介面。如果使用.def檔案,需要在編譯選項進行配置,如:

使用.def檔案麻煩的地方是每次更新介面都要手工更新.def檔案,但是使用.def檔案有一個好處是當dll發生更新以後,如果定義的ordinal沒有發生改變的話,調用方不需要重新連結程式就可以使用新的DLL,Windows Mobile的今日組件就是使用.def檔案進行定義的,需要實現ordinal為240和241兩個介面:

InitializeCustomItem        @240    NONAME
CustomItemOptionsDlgProc @241 NONAME

這樣shell32進程就可以載入實現了這兩個介面的DLL,不需要重新串連來支援新的組件。

 

方案二: __declspec(dllexport)

我個人偏向於使用__declspec(dllexport)的方案,因為P/Invoke不存在調用方重新連結的問題,所以我偏向於使用__declspec(dllexport)的方案。

使用__declspec(dllexport)的方案,在需要輸出的函數加入__declspec(dllexport)。這樣該函數就會產生輸出表。

#define EXPORT_API __declspec(dllexport)
EXPORT_API BOOL OpenIndicator()
{
return TRUE;
}

例如上述定義產生以下輸出。使用Dumpbin /exports進行查看。

Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.


Dump of file NativeLib.dll

File Type: DLL

Section contains the following exports for NativeLib.dll

00000000 characteristics
4AF757EA time date stamp Sun Nov 08 10:44:42 2009
0.00 version
1 ordinal base
1 number of functions
1 number of names

ordinal hint RVA name

1 0 0000BA30 ?OpenIndicator@@YAHXZ = ?OpenIndicator@@YAHXZ (int __c
decl OpenIndicator(void))

Summary

1000 .data
2000 .pdata
2000 .rdata
2000 .reloc
19000 .text

有沒有發現輸出是?OpenIndicator@@YAHXZ 而不是 OpenIndicator。

如果.NET Compact Framework的調用方如下:

[System.Runtime.InteropServices.DllImport("DeviceCommsLib.dll", SetLastError = true]
private static extern bool OpenIndicator();

程式執行的時候會拋出找不到進入點的異常,如:

原因是產生輸出的時候使用C++的命名輸出了?OpenIndicator@@YAHXZ 而不是 OpenIndicator。如果要解決這個問題,有兩個辦法:方法一,在調用方指定進入點:

[System.Runtime.InteropServices.DllImport("DeviceCommsLib.dll", SetLastError = true, EntryPoint = "?OpenIndicator@@YAHXZ")]
private static extern bool OpenIndicator();

這個辦法不好,因為調用方需要使用Dumpbin /exports查看輸出進入點。

 

 

 

方法二,增加extern "C",如下:

#define EXPORT_API __declspec(dllexport)
extern "C" {
EXPORT_API bool OpenIndicator()
{
return true;
}
}

這樣使用了C的命名,使用Dumpbin /exports查看輸出如下:

Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.


Dump of file NativeLib.dll

File Type: DLL

Section contains the following exports for NativeLib.dll

00000000 characteristics
4AF75999 time date stamp Sun Nov 08 10:51:53 2009
0.00 version
1 ordinal base
1 number of functions
1 number of names

ordinal hint RVA name

1 0 0000BA30 OpenIndicator = OpenIndicator

Summary

1000 .data
2000 .pdata
2000 .rdata
2000 .reloc
19000 .text

輸出介面變成OpenIndicator 了。

 

總結

總結一下,如果有Native C++的共用靜態庫需要提供給.NET Compact Framework調用,首先建立一個win32的DLL,把改靜態庫連結到這個DLL裡面,然後定義DLL通過extern "C" __declspec(dllexport) 來輸出出介面,最後在.NET Compact Framework程式就可以通過P/Invoke來調用原先在靜態庫中的功能模組來。

關於P/Invoke,我原先寫過些文章可以參考。

.NET Compact Framework 下Win32 API P/Invoke 的使用

開發P/Invoke的工具與Website

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.