博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Mobile和Wince(Windows Embedded CE)下如何封装Native DLL提供给.NET Compact Framework进行调用...
阅读量:6073 次
发布时间:2019-06-20

本文共 3480 字,大约阅读时间需要 11 分钟。

背景

在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。如果要解决这个问题,有两个办法:方法一,在调用方指定入口点:

[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,我原先写过些文章可以参考。

转载地址:http://omngx.baihongyu.com/

你可能感兴趣的文章
HDU 6140 Hybrid Crystals
查看>>
【查漏补缺】普通类中获取有注解的类
查看>>
loadrunner Error -27985问题
查看>>
python之使用__future__
查看>>
蜘蛛纸牌存档文件,读取分数
查看>>
体重计算
查看>>
hdu1241 Oil Deposits (bfs水题)
查看>>
js数组的sort排序详解(转载)
查看>>
网页各类宽高
查看>>
postSharp,INotifyPropertyChanged的AOP植入
查看>>
毕业论文管理系统——面向对象方法
查看>>
2016-7-6
查看>>
FTP服务器
查看>>
Tumblr's David Karp Told the New York Times the Interesting topics
查看>>
树状数组
查看>>
对象练习
查看>>
每日练习
查看>>
[原]Unity3D深入浅出 - 认识开发环境中的Component(组件)菜单
查看>>
回调函数
查看>>
Android开发中常见的内存泄露案例以及解决方法总结
查看>>