C++ Coder

HCP高性能计算架构,实现,编译器指令优化,算法优化, LLVM CLANG OpenCL CUDA OpenACC C++AMP OpenMP MPI

C++博客 首页 新随笔 联系 聚合 管理
  98 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks

#

     摘要: http://www.cnblogs.com/linzheng/archive/2012/06/30/2571281.html Windows 8 的metro风格应用程序的开发编程和Windows phone 7是非常类似的,不过Windows 8对开发语言的支持是比Windows Phone 7强大很多,支持C++,C#和JavaScript,而Windows Phone 7只是支持C#,当...  阅读全文
posted @ 2012-10-29 21:35 jackdong 阅读(435) | 评论 (0)编辑 收藏


    看了个BUILD的PPT,Windows Runtime (RT)并不是一些新闻网站说的那样微软自废.NET武功,而是恰恰相反,WinRT是Win32API的现代版,其中有很深的.NET的基因,是Metro UI的.NET基础,如果考察Metadata的变化,WinRT的API定义的元数据是基于标准ECMA 335,也就是.NET的标准 ,WinRT也是一个沙箱的环境,针对AppStore环境设计的。

基础知识

微软以推出Windows 8为契机,以解决Windows长期存在的问题,并带来了新的用户界面,使得Windows更加安全和AppStore的商业模式。微软在Windows 8 里打造了第三个 XAML-based UI 系统, WPF只是一个供 .NET 这个圈子使用的XAML UI系统 Silverlight只是给浏览器使用的XAML UI系统,Windows Phone7将Silverlight到了手机,现在将XAML带到了涵盖PC、Pad、Phone的所有系统(虽然微软认为平板也是PC,我还是想叫他Pad,用过iPad的都知道苹果所定义的Pad和PC有很大区别)。

.NET开发人员都对.NET 的P / Invoke和COM Interop 很熟悉了,这两种技术使得.NET人员可以使用Win32 API和COM组件,Mono也是使用P/Invoke技术创建原生的库,例如Gtk# 绑定到 Gtk+ API, MonoMac 绑定到Cocoa API, Qyoto 绑定到Qt API,Mono出现了MonoTouch,MonoDroid和MonoMac等等很有创新性的产品。 COM Interop 还可以使得C/C++ 从 C#导入Com类型库。

创建原生库的方法很多,但是这些工作都得是手工去做,很乏味而且容易出错,从这点来说WinRT也是一个很有创新的,可以让所有的开发者用同一个模型创建Metro UI的应用。

WinRT

WinRT是一个新的API 集合,具有以下特性:

  • 它实现了Metro UI规范的UI库
  • 为Windows开发人员提供一个简单的UI编程模型,你不需要学习Win32API的那些复杂的API了
  • 它使用XAML-base的UI系统
  • API都设计成了异步的
  • 它和.NET一样是个沙箱的API,自成体系,用于创建AppStore上的应用程序。
  • API的元数据格式是ECMA335,和.NET一样的标准。这是不是意味着以后Mono也可以在xUnit上去实现这样的API呢?

WinRT包装的新的用户界面系统,和Win32API一样是Com的上层。

WinRT Projections

我们所说的“Binding”,微软现在叫做“Projections”,又是一个新名词。Projections就是向三个环境 Native (C and C++), HTML/Javascript 和.NET 暴露接口的过程。所以在Win8上各类开发者依然可以用着不同的工具,但是却是使用着统一的模型。

如果开发者使用.NET或者C++ 写的组件,它的API被存储在一个WinMD文件里,你可以在三种环境(原生、javascript和.NET)。即使你的组件是用C++ 写的,也不需要通过COM向外暴露,使用起来更像是一个面向对象的C++ API。

WinRT的底层定义了一套基本的类型和各种环境的映射,这是不是很像.NET环境里面对不同语言的支持哈。

异步API

微软认为,当给开发者一个使用同步和异步的API的选择的时候,开发者会选择简单的同步API,这在我们的.NET 编程实践中得到证明,.NET有很成熟的异步编程模型,还有特意为并行和异步处理而设计的F#,结果是什么呢,各位同学心里有数。

在WinRT中,微软一直遵循一个简单的规则:如果一个API预计耗时超过50毫秒,那么API就是异步的,也就是说API是异步的哦,这样就能确保Metro UI上的操作体验是最好的。

异步编程历来是一个繁琐的过程,回调和状态,还有异常处理等。为了简化这个过程,C#和VB也扩展了支持 F#-inspired await/async 模型,异步编程变成了欢乐之旅。

.NET的首要地位不见了吗?

之前的新闻中一直在质疑.NET 被微软抛弃了,当然不是了。也不是所有的.NET API 都集成到了WinRT中,只是一个子集。

当你使用C#和VB,你使用的是完整的.NET框架。但是他们只暴露了一个较小的子集API给Windows 8的开发者。你可能会想,我可以通过一些技巧使用到整个.NET,如果你的程序不需要提交AppStore上接受微软的审核,这是可以的。这种策略明显是跟苹果学的。

借此机会.NET团队也对.NET做了一次清理,mscorlib.dll和System.dll中已被分割在不同的库里头了,随着Win8发布的.NET版本是4.5了,也就是说.NET 4.5不是.NET 4的简单补丁包,里头加了不少东西,ASP.NET的版本号也是4.5,不像.NET 2.0 ~3.5 SP1,ASP.net的版本还是2。0。为了在Win8里开发,开始学习.NET 4.5又是必须的了,这里关注的集中在客户端开发,同样的在服务器端开发方面.NET 4.5也加入大量的干货。

创建WinRT 组件

虽然WinRT支持很多的语言,但是微软只是用C++和.NET演示了如何开发一个WinRT组件,使用.NET来开发WinRT组件会比C++简单得多。也不是所有的.NET特性都能用上哦,比如组件类就不能使用private 字段,在异步的API里不能使用Task<T> ,要用IAsyncOperation 代替。

public sealed class AddTwo
{
public int Add (int a, int b)
{
return a + b;
}

public async IAsyncOperation SubAsync (int a, int b)
{
return a - await (CountEveryBitByHand (b));
}
}

你会发现上述代码没有任何形式的COM声明,唯一限制的是,类必须是个密封的(除非你是在创建一个XAML UI组件,这种情形下这种限制是接触的)

UI编程

当涉及到用户界面的开发的时候,你你可以使用HTML与CSS样式或使用XAML的你的应用程序的用户界面。当你回到界面层,就可以用HTML & CSS或者是XAML UI,用HTML& Css做出来的界面就是Web了,而是一个Windows应用,早在Vista开始就有了类似的应用,Windows7上做了改进,叫做Gadgets ,Windows 8就进化到了Metero UI,和C++、.NET并驾齐驱了。

Windows8的开发框架并没有基于HTML5和JavaScript,开发者完全可以用原生C++、C#和Silverlight去开发对平板和触控友好的应用,HTML5和JavaScript只是提供了一种选择。

作者: 自由、创新、研究、探索……
出处:http://shanyou.cnblogs.com/
版权:本文版权归作者和博客园共有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
posted @ 2012-10-29 21:30 jackdong 阅读(495) | 评论 (0)编辑 收藏

 英文原文:C# and Visual Basic on the WinRT API

  (作者:Jonathan Allen 译者:侯伯薇

  尽管我们可以使用 .NET 语言来调用 Win32 API,但那样做会很困难。所以在过去的两年间微软一直在构建替代的方案,它就是实现了跨语言支持的 Windows 运行时,即 WinRT。我们可以在 C++ 和 .NET 中创建 WinRT 组件,并且可由二者以及 JavaScript 使用。

  尽管 COM 在表面上是一种基于 OOP 的框架,但它与 .NET 之间有很大的区别。在 WinRT 出现之前,COM 是基于接口而不是基于类的。这意味着其中缺少很多 .NET 开发者认为应该有的内容,像构造函数以及静态方法等。C++组件扩展解决了这个问题。

  WinRT 形式的 COM 使用的元数据格式和通用语言运行时(Common Language Runtime)相同。这些信息存储在表示结构的 WINMD 文件中,尽管没有实现,但在所有公有类中都会有。FXCop 被用于检验这些文件所暴露的 API 是否遵循 .NET Framework 的设计指南。

  .NET 在最开始时就有“API 设计委员会(API Design Board)”。受此启发,Windows 运行时也会建立 API 设计委员会来对其进行管理。很多最初的成员都在 .NET 委员会中,并且很多指南都直接来自于 .NET 基本类库所遵循的原则。

  Windows 运行时会返回 HRESULT,而不会抛出异常。对于众所周知的 HRESULT 值来说,会抛出相应的异常,而对于其他值就只能抛出 COMException。

  WinRT 的 IAsyncOperation 接口现在使用新的 async/await 关键字,就像 .NET 的 Task 对象一样。

  所有 Windows 运行时的集合接口都被映射到 .NET 框架的等价物上。在 .NET 4.5中添加了 IReadOnlyList 和 IReadOnlyDictionary,用来负责处理 WinRT 中的只读集合。

  WinRT 和 .NET API 在两个地方无法匹配。WinRT 的 stream 无法直接与 .NET 的 IO.Stream 类兼容,但是可以调用名为 AsStream 的扩展方法来进行转换。WinRT 还拥有名为 IBuffer 的接口,这在 .NET 中也无法简单地实现。在此也有一个扩展方法来进行 IBuffer 和比特数组之间的转换。

  我们可以使用 C# 和 VB 来创建新的 Windows 运行时程序库,过程非常简单。为了把类暴露为 Windows 运行时组件,我们只需要把项目类型设置为“WINMD 文件”,并确保遵循以下规则:

  1. API 签名只使用 Windows 运行时的类型
  2. 结构体只能拥有公有的数据字段
  3. 只允许对 XAML 控件使用继承,其它类型都必须使用 sealed 关键字。
  4. 只支持内建的泛型

  编译这些库之后,我们就可以在 C++ 和 JavaScript 中调用它们,就像从 .NET 中调用一样简单。

  警告

  由于 WinRT 是基于 COM 构建的,所以你同样会有引用计数和 mark-and-sweep 垃圾回收器之间无法融合的问题。对于实现了析构函数释放非内存资源的对象来说,这是最常见的问题。我们可以考虑调用“Marshal.FinalReleaseComObject”来解决问题,但是那本身也存在问题。

  COM 风格的 marshaling 需要在 .NET 和本地组件之间调用。尽管这通常是无关紧要的,但是如果 API 非常不正式,那么就会出现问题。

  内建的 WinRT 库(而不是 XAML)是在 Metro 运行时环境之外提供的。然而,第三方的 WinRT 库并非如此。这是 WinRT 中激活框架(activation framework)的限制,而不是 .NET 的问题。

posted @ 2012-10-29 21:27 jackdong 阅读(232) | 评论 (0)编辑 收藏

http://www.ithov.com/article/118831.shtml

对于 Windows 8,我们彻底颠覆改造了平台,您可以选择您已了解的编程语言和技术来构建为设备和外形因素定制的应用。而对于 Windows 运行时,您甚至可以在单一应用中轻松地使用多种语言。通过使用 C++ 来构建您自有的 Windows 运行时组件,您可以通过可与 Xbox 360 控制器交互的 HTML 和 JavaScript 来构建出色的 Metro 风格应用。您可以构建通过 Windows 运行时组件公开的可重用 XAML 控件,这些控件可供使用 C++ 和 C# 编写的 Metro 风格应用即时使用。实质上,我们已允许您在 Windows 8 平台上使用您选择的语言并以毫不迁就的方式来构建应用。

在本篇博文中,我们将讨论构建 Windows 运行时组件所需了解的必要知识。

基础知识

Windows 运行时是实现语言选择的核心。它自身是公开的,从而您可以从 JavaScript、C++、C# 和 Visual Basic 中以自然而熟悉的方式对其进行调用。这种基础方法也同样适用于构建您自有的 API。

您在应用中构建和打包的 Windows 运行时组件通常被称作第三方 Windows 运行时组件。这与已作为 Windows 8 平台中一部分的第一方组件有所不同。您可以使用 C++、C# 或 Visual Basic 编写这些第三方 Windows 运行时组件。您可以从任何位置调入它们公开的 API,包括打包到您的应用中的其他 Windows 运行时组件。您也可以使用任何语言来调入通过 Windows 运行时组件公开的 API。

您为应用编写的 Windows 运行时组件可使用 Windows 运行时 API、Win32、COM、.NET API 或第三方库(只要它们支持 Metro 风格应用开发)。请注意您所构建的 Windows 运行时组件与传统意义上公开 API 的 C++ DLL 或 .NET 程序集并不相同。使用 .Net 创建类库或者使用 C++ 创建独立的 DLL 与构建 Windows 运行时组件完全不同。Windows 运行时组件在公开 Windows 运行时元数据的 .wnmd 文件中声明,并且允许 JavaScript 等语言来自然地使用 Windows 运行时 API(例如,向 JavaScript 公开的 API 的 pascalCasedNames 支持)。Windows 运行时元数据还允许 Visual Studio 提供出色的工具功能,如 IntelliSense 支持。

为何要构建您自有的 Windows 运行时组件

创建 Windows 运行时组件可帮助您对可重用性和语言互操作性进行设计。我们来看一下展示如何使用第三方 Windows 运行时组件来构建更佳体验的一些应用程序方案。


在您的 Metro 风格应用中使用 Win32 和 COM API

Internet Explorer 10 提供的平台允许您使用 HTML、CSS 和 JavaScript 创建出色的 Metro 风格应用体验。但是,如果您已使用 HTML5 Canvas 构建游戏,并希望与 Windows 的 Xbox 360 控制器相集成,那情况会怎样?允许应用从控制器接收输入的 XInput API 会将不可用的 Win32 API 直接向 JavaScript 公开。

这是通过创建 Windows 运行时组件来解决该问题并使您能够在基于 HTML 的 Metro 风格应用中使用 XInput API 的经典示例。XInput 和 JavaScript 控制器草图示例准确地展现了这一点。该示例应用包含一个游戏控制器 Windows 运行时组件,它使用 C++ 编写并用于包装 XInput API 公开的功能。该控制器草图基于 HTML 的应用使用游戏控制器 C++ Windows 运行时组件来实现与 Xbox 360 控制器的交互。

这一方案(无法单独使用 HTML 和 JavaScript 实现)是通过创建第三方 Windows 运行时组件来完成通过其他方法无法完成的复杂方案的完美示例。

大计算量的操作

为诸如科学、工程和地图/地理等字段创建应用通常需要大计算量的操作。这些大量的操作通常需要强大的并行处理且非常适合于使用 C++ 获得最佳性能。在开发 Bing 地图旅行优化器(使用 JavaScript 和 C++ 开发的 Metro 风格应用)中,我们看到了另一种方案,即使用 C++ 创建 Windows 运行时组件使我们可以创建最佳的应用体验。

您可能会考虑为何用户完全使用本地数据计算旅行路线,而他们可以在云端的 Bing 服务器上运行这种大计算量的操作。Bing 地图为公开执行此操作的 JavaScript API,而有时应用必须脱机运行。另外,我们也希望用户通过触控实时拖动和更改路线。如果我们在本地运行此类大量的操作,则我们需要创建甚至更好的体验。

通过使用并行任务类库而用 C++ 编写大计算量的操作,我们可以利用客户端的强大功能来为用户创建出色的使用体验。Windows 运行时可完美适用于该方案,它允许我们使用 Bing 地图 AJAX 控件来创建使用 HTML 和 JavaScript 的丰富用户界面 (UI),而使用 C++ 代码运行的所有大量路线操作可通过并行计算提高计算的速度。


社区中拥有着大量而出色的库,开发人员已进行汇总并与广大用户共享。在过去,您可能会认为重用其中的一些库可能很具挑战性,如果它们与实现您的应用的编程语言不匹配的话。例如,您构建了一个出色的 .NET 应用,但必须完成痛苦的互操作蓝框(如 PInvoke),才能使用通过 C++ 编写的库。

Windows 运行时可以弥合 Windows 8 中的语言分歧,使包含单个基本代码的单一 Windows 运行时组件库可以扩展至更广泛的开发人员,无论组件的语言或应用的主要编程语言是什么。

现在,您可以创建一个可供全部 C++ 和 C# 开发人员使用的公开 Windows 运行时的单一 XAML 自定义控件。您可以在您的基于 XAML 或 HTML 的 Metro 风格应用中使用由开发人员共享的各种数据存储 Windows 运行时库。所有这些方案均无需编写互操作代码即可实现。

我们认为 Windows 运行时将惠及由开发人员创建并与社区中广泛的 Metro 风格应用��发人员共享的各种库。现在,我们来看看两个展示使用 C++/CX 和 C# 构建第三该 Windows 运行时组件的具体示例。

应用场景 1:通过本机音频来增强您的应用

假设我们要使用拥有 C# 编写的应用逻辑支持的 XAML 来构建一个软件合成器应用。为了向我们的音乐应用添加过滤器,我们将使用 XAudio 来直接控制音频缓冲器。

将 Windows 运行时组件添加到我们的解决方案

使用 Visual Studio,我们可以将全新的 C++ Windows 运行时组件项目添加到我们现有的解决方案。该 Windows 运行时组件包括音乐处理功能:

使用 Visual Studio 来将一个全新的 C++ Windows 运行时组件添加到我们的音乐应用
图 2:添加一个全新的 C++ Windows 运行时组件

Visual Studio 为我们创建了一个 C++ 项目,用于公开 API,而 API 的实现将打包到一个 DLL 文件,而 Windows 运行时元数据将打包到 winmd 文件中。它们全部可用于我们的 C# 项目。

定义向我们的 XAML C# 项目公开的类

我们使用 C++/CX 来构建向 C# 项目公开的 API,但您也可以使用 Windows 运行时 C++ 模板库 (WRL)。我们首先定义一个非常基本的类以封装 XAudio 功能:

XAudioWrapper.h

#pragma once

#include "mmreg.h"
#include <vector>
#include <memory>

namespace XAudioWrapper
{
    public ref class XAudio2SoundPlayer sealed
    {
    public:
        XAudio2SoundPlayer(uint32 sampleRate);
        virtual ~XAudio2SoundPlayer();

        void Initialize();

        bool   PlaySound(size_t index);
        bool   StopSound(size_t index);
        bool   IsSoundPlaying(size_t index);
        size_t GetSoundCount();

        void Suspend();
        void Resume();

    private:
        interface IXAudio2*                     m_audioEngine;
        interface IXAudio2MasteringVoice*       m_masteringVoice;
        std::vector<std::shared_ptr<ImplData>>  m_soundList;
    };
}

首先,您必须注意类声明中 public、ref 和 sealed 等关键字的使用。对于通过 JavaScript 或 C# 等其他语言在 Metro 风格应用中实例化的类来说,该类必须声明为 public ref class sealed。

类的公共功能(方法、属性等)仅限于 C++ 内置的类型或 Windows 运行时类型。这些是可在 Windows 运行时组件中跨越语言界限的唯一类型。但话虽如此,您仍然可以将常规的 C++ 库(即标准模板库集合)用于您的类中的专用数据成员,如在该代码断中所示。这些专用数据成员无需遵从与跨越语言界限有关的规则。如果您使用不支持的构造,则 Visual Studio 编译器将发出错误消息并提供相应的指导。

 

实现在我们的 Windows 运行时组件中公开的类

现在,我们已定义了类的基本接口,接下来让我们来看看一些实现方法:

XAudioWrapper.cpp

XAudio2SoundPlayer::XAudio2SoundPlayer(uint32 sampleRate) :
m_soundList()
{
// Create the XAudio2 engine
UINT32 flags = 0;

XAudio2Create(&m_audioEngine, flags);

// Create the mastering voice
m_audioEngine->CreateMasteringVoice(
&m_masteringVoice,
XAUDIO2_DEFAULT_CHANNELS,
sampleRate
);
}

void XAudio2SoundPlayer::Resume()
{
m_audioEngine->StartEngine();
}

bool XAudio2SoundPlayer::PlaySound(size_t index)
{
//
// Setup buffer
//
XAUDIO2_BUFFER playBuffer = { 0 };
std::shared_ptr<ImplData> soundData = m_soundList[index];
playBuffer.AudioBytes = soundData->playData->Length;
playBuffer.pAudioData = soundData->playData->Data;
playBuffer.Flags = XAUDIO2_END_OF_STREAM;

HRESULT hr = soundData->sourceVoice->Stop();
if (SUCCEEDED(hr))
{
hr = soundData->sourceVoice->FlushSourceBuffers();
}

//
// Submit the sound buffer and (re)start (ignore any 'stop' failures)
//
hr = soundData->sourceVoice->SubmitSourceBuffer(&playBuffer);
if (SUCCEEDED(hr))
{
hr = soundData->sourceVoice->Start(0, XAUDIO2_COMMIT_NOW);
}

return SUCCEEDED(hr);
}

在该代码段中,我们使用可用于 Metro 风格应用开发的 XAudio2 COM API 来连接我们的音频引擎、播放声音和恢复引擎。另外,我们还可以使用 C++ 构造和除 Windows 运行时类型以外的其他类型来实现必要的功能。

添加和使用 Windows 运行时组件

在定义和实现基本类之后,我们使用 Visual Studio 来将 XAudioWrapper Windows 运行时组件从我们的 C# 项目添加到 C++ 项目:

使用 Visual Studio 来将 XAudioWrapper Windows 运行时组件的引用添加到我们的音乐应用

图 3:将 XAudioWrapper Windows 运行时组件添加到我们的音乐应用

因此,我们从 C++ 项目公开的类可用于我们的 C# 项目:

MainPage.cs

using XAudioWrapper;

namespace BasicSoundApp
{
public sealed partial class MainPage : Page
{
XAudio2SoundPlayer _audioPlayer = new XAudio2SoundPlayer(48000);
public MainPage()
{
this.InitializeComponent();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
_audioPlayer.Initialize();
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
_audioPlayer.PlaySound(0);
}
}
}

如在该代码段中所示,我们可以像使用常规 .NET 组件那样与 C# 中的 XAudio 封装程序进行交互。我们将引用其命名空间、举例说明组件并开始调用其公开的各种方法。所有这一切不需要任何 DllImport 来调入本机代码!

应用场景 2:使用内置的 API 在您的应用中打开 zip 文件

假设我们使用 HTML 来构建文件查看器应用,并希望添加功能来允许该应用的用户选取 zip 文件。我们希望将 Windows 中已内置并在 .NET 平台中公开的 API 用于处理 zip 文件。

将 Windows 运行时组件添加到我们的解决方案

该步骤与我们在音乐应用中所描述的步骤完全相同,现在我们将选取 C# Windows 运行时组件来包装 zip 处理功能:

使用 Visual Studio 来将一个全新的 C# Windows 运行时组件添加到我们的文件查看器应用
图 4:添加一个全新的 C# Windows 运行时组件 

Visual Studio 为我们创建了一个 C# 项目,用于公开 API,而 API 的实现和 Windows 运行时元数据都将打包到 .winmd 文件,并且可用于我们的 Web 项目。


实现在我们的 Windows 运行时组件中公开的类

我们使用 C# 来构建将向我们的 Web 项目公开的 API,但您同样可以使用 Visual Basic。我们首先定义一个简单的 C# 类来封装 zip 功能:

ZipWrapper.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Storage;

public sealed class ZipWrapper
{
public static IAsyncOperationWithProgress<IList<string>, double> EnumerateZipFileAsync(StorageFile file)
{
return AsyncInfo.Run(async delegate(
System.Threading.CancellationToken cancellationToken, IProgress<double> progress)
{
IList<string> fileList = new List<string>();
progress.Report(0);

using (var stream = await file.OpenStreamForReadAsync())
{
using (var archive = new ZipArchive(stream))
{
for (int i = 0; i < archive.Entries.Count; i++)
{
// add code for processing/analysis on the file
// content here

// add to our list and report progress
fileList.Add(archive.Entries[i].FullName);
double progressUpdate = ((i + 1) / ((double)archive.Entries.Count)) * 100; // percentage
progress.Report(progressUpdate);
}
}
}

progress.Report(100.0);
return fileList;
});
}
}

该类是公共的且已密封。类似于构建 C++ Windows 运行时组件,这对于其他语言实例化类来说是必需的。该类中公开的静态方法混合使用 Windows 运行时类型(例如,StorageFile),并且在方法签名中作为 .NET 类型(例如,IList)。我们的经验法则是使用 Windows 运行时类型来定义向其他语言公开的公共字段、参数和返回类型。尽管如此,您仍然可以原封不动地使用某些 .NET 基本类型(即 DateTimeOffset 和 Uri)以及基元(即 IList)。

您还会注意到上述方法利用了在定义您的 Windows 运行时组件时可以(且应该)使用的用于异步性和进度支持的 Windows 运行时基础结构。就该类中的 Windows 运行时组件或任何专用功能的实现而言,您并不仅限于使用 Windows 运行时类型和 API;您可以自由使用任何向 Metro 应用开发公开的 .NET API 表面,如代码段 ZipArchive API 中所示。

添加和使用 Windows 运行时组件

我们现在已经实现了 zip 工具封装程序,我们将使用 Visual Studio 来添加我们的 JavaScript 项目中对 C# 项目的引用:

使用 Visual Studio 添加我们的文件查看器应用中 ZipUtil Windows 运行时组件的引用
图 5:将 ZipUtil Windows 运行时组件添加到我们的文件查看器应用
 

因此,我们从 C# 项目公开的类将可用于我们的 Web 项目:

program.js

function pickSinglePhoto() {

// Create the picker object for picking zip files
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
openPicker.fileTypeFilter.replaceAll([".zip"]);

// Open the picker for the user to pick a file
openPicker.pickSingleFileAsync().then(function (file) {
if (file) {
ZipUtil.ZipWrapper.enumerateZipFileAsync(file).then(
function (fileList) {
for (var i = 0; i < fileList.length; i++)
document.getElementById('output').innerHTML += " " + fileList[i];
},
function (prog) {
document.getElementById('zipProgress').value = prog;
}
);
} else {
document.getElementById('output').innerHTML = "an error occurred";
}
});
};

正如您所看到的,我们可以与 JavaScript 中我们的 zip 工具封装程序进行交互,如同它是一个常规的 JavaScript 对象。我们可以调入 Windows 运行时组件中公开的静态方法,而我们使用 JavaScript 的异步语言构造,如 .then(),也可以完成此操作。

一般指导

并非您为 Metro 风格应用编写的所有 API 都应公开为第三方 Windows 运行时组件。通常情况下,当您在不同的编程语言之间进行通信时需要使用 Windows 运行时组件类型,并使用语言中内置的类型和构造来实现无法通过 Windows 运行时组件全局公开的功能。另外,跨越语言界限还涉及各种语言特定的功能和规则,当构建 Windows 运行时组件时,您必须将其纳入考虑范围。它们具体包括代理和事件、异步操作、方法重载和处理特定的数据类型(例如,集合、异常处理和调试技巧)。您可以通过访问构建 Windows 运行时组件中面向您的开发语言的部分,来深入研究这些主题。

总结

就 Windows 运行时组件而言,您现在可以混合使用编写语言和 API 技术来构建您设想的应用。毫不迁就的理念贯穿于 Windows 8。即使是在开发阶段情况依然如此,我们允许您混合使用和匹配适用于您的方案的最佳编程语言。我希望这将使您能够用更多的时间来考虑创新,而不是在学习全新的编程语言方面浪费大量的时间。

希望您能充分享受构建应用为您带来的快乐!

-- Windows 项目经理 Ines Khelifi


posted @ 2012-10-29 21:16 jackdong 阅读(293) | 评论 (0)编辑 收藏

 

    WinRT 不是另一个抽象层;它就像 Win32 API 一样,直接驻留在内核之上。自从 1993 年 Win32 伴随 Windows NT 被引入以来,这标志着对于 Windows 核心的首次重大突破。WinRT 与 Win32 截然不同,它代表了新的语义学应用程序执行环境。
 

  不像 Win32 是用C语言思想设计的,而 WinRT API 是用 C++ 编写的,并且从一开始的设计就是面向对象的。一致性、易用性、以及性能都是新的运行时 API 的重要方面。WinRT API 中的每个对象都支持反射,以便甚至连诸如 JavaScript 等动态语言都可有效地使用它们。随之而来还有统一对象模型,这对于基于库的 C++ 而言是个稀罕物。

  附注:Win32 API 并未被移除,而且那些使用传统应用程序执行环境的较早的应用程序将继续按预期方式工作。

  C++开发

  在 C++ 中编写用户界面将首选 XAML。所有与 XAML 一起使用的库都已被移植到C++,并且被编译为本地 x86 版本。使用 XAML 和 C++ 编写的 Metro 风格应用程序并不运行在 .NET 之上,它们就像其他任何 Visual C++ 应用程序一样,被直接编译为 x86 版本。

  调用 UI 控件的方法就像在 C++ 中调用任何其他对象的方法一样。在机器码级别上,某个指令将 this 指针推送到堆栈上,然后通过虚函数表(v-table)调用相应函数。这使得即使在低功耗设备上也能达到最优的性能。

  支持一些现代的 C++ 应用程序所用的库,例如 Boost。

  重叠窗口不复存在

  对话框是来自上一版 Windows 的核心概念,而在 WinRT 中它将不复存在。对于微软而言,性能成本和可用性问题已不再是理所当然的。希望使用这种模式的应用程序将要开发其他的方式来传递信息,例如消息框的方式。

  另一并未纳入 WinRT 的库是 GDI。如果某个应用程序要使用 Metro 风格界面,那么它需要按自上而下的方式来做,将 Metro 风格与经典用户界面相混合的情况是不可能出现的。

  PlayTo 契约

  另一被公开的契约是 PlayTo(由……发挥)。这使得应用程序可发送如音频及视频等媒体文件到某个 charm[1]。然后那个 charm 将允许用户选择某个他们想用的应用程序来查看该文件。据推测,媒体文件不仅限于物理文件,而是任何可表示为数据流的媒体形式。

  C#/VB:平台调用(P/Invoke)之终结

  从 .NET 中调用本地函数通常涉及建立结构和操纵指针。而在 WinRT 环境下,所有的 API 被公开为许多可通过 C# 及 VB 直接使用的对象。这把 .NET 开发者置于与 C++ 开发者平等的层面上。

  应用程序的响应速度对于微软而言是非常重要的。所有耗时超过 50 毫秒的操作系统级别的 API 调用将被公开为异步操作,正是为了向开发者传递这种价值观。

  JavaScript

  对于 Windows 8 而言,第四大语言就是 JavaScript。尽管它不使用 XAML,但它就像本地及 .NET 应用程序一样,拥有对底层 WinRT API 的直接访问权。这不仅是个像 PhoneGap 一样的容器,JavaScript 开发者还可获得与其他开发者所使用的同样丰富的 API。

  由于是 JavaScript,因此所选择的 UI 工具包是 HTML 和 CSS 而非 XAML。IE 10 及 Metro 风格的 JavaScript 应用程序使用的是同一渲染引擎,尽管那些应用程序实际并不运行在浏览器中。JavaScript 应用程序看起来就像任何其他 Metro 风格应用程序一样。

  JavaScript 中的用户控件几乎与 C++ 及 .NET 中的控件不相上下。有些控件对于 HTML 渲染引擎而言是固有的,而另外一些控件则是用 JavaScript 编写的。这些基于 JavaScript 的控件都是基于 div 的,非常像那些使用 jQuery 创建的控件。

  应用程序容器和应用程序权限

  Metro 风格应用程序运行在被称为“应用程序容器”(app container)的环境中。这似乎取代了由基于 Win32 应用程序所使用的窗体环境。

  大多数 API 调用被直接发送给底层内核。然而,有些调用将被通过系统代理(system broker)路由。系统代理确保应用程序只能访问那些经用户已批准的功能。例如,当某个应用程序首次尝试访问摄像头时,服务代理(service broker)将提示用户以获取他们的批准。应用程序必须包括一份清单,其中注明该应用程序可能需要的所有限制服务。这种模式对于移动设备开发者而言将是非常熟悉的。

  所有 Metro 风格应用程序都会运行在 WinRT 的应用程序容器中,而且会受到系统代理的监控,甚至连那些用 C++ 编写的应用程序也不例外。该思想是为了限制应用程序破坏系统的能力。虽然也许并不是不可能的,但是在 WinRT 下创建恶意软件与在 Win32 中相比将会难得多。

  所有 Metro 风格应用程序必须进行数字签名

  不允许匿名应用程序。应用程序为了测试可进行自签名,但是当它们出现在应用商店里时,它们就必须使用真实证书进行签名。

  译注

  [1] charm,微软已将“CHARM”注册为计算机、软件产品、电气和科学产品类商标。微软将 CHARM 描述为计算机程序、图形用户界面软件和操作系统程序。在触摸版 Windows 8 中,charms 在屏幕右侧;在传统版(使用鼠标和键盘)Windows 8 中,charms 出现在屏幕左侧。charms 包括:Search(搜索)、Share(分享)、Start(开始)、Devices(设备)、Settings(设置)。详见微软申请 Windows 8 功能 charm 注册商标(图)。

  作者:Jonathan Allen 译者:高翌翔

  查看英文原文:WinRT: An Object Orientated Replacement for Win32 

  相关博客文章:Windows Runtime(WinRT) 揭秘


http://dotnet.cnblogs.com/page/115787/
posted @ 2012-10-29 15:21 jackdong 阅读(363) | 评论 (0)编辑 收藏

http://blog.csdn.net/dongjun7357/article/details/6277682

一、GProfile简介

      GProfile是gcc的一个工具,用于对应用程序的测试。

      GProfile可以分析出函数的调用次数、函数的调用关系以及函数消耗的时间。

 

二、GProfile原理

      在编译和链接你的程序的时候,gcc 在你应用程序的每个函数中都加入了一个名为mcount ( or "_mcount" , or "__mcount" , 依赖于编译器或操作系统)的函数,也就是说你的应用程序里的每一个函数都会调用mcount, 而mcount 会在内存中保存一张函数调用图,并通过函数调用堆栈的形式查找子函数和父函数的地址。这张调用图也保存了所有与函数相关的调用时间,调用次数等等的所有信息。 

     程序运行结束后,会在程序退出的路径下生成一个gmon.out文件,用来保存监控数据。从而通过gprof来解读数据对程序进行分析。

          

三、GProfile用法

      1、在编译时加入参数 -pg就可以打开GProfile的开关。

      2、gprof只查看用户函数信息,不能对库函数进行查看。 如果想查看库函数的信息,在编译时加入"-lc_p"编译参数代替"-lc"编译参数,这样程序会链接libc_p.a库,就可以查看库函数的信息了。 
  3、 gprof只能在程序正常结束退出之后才能生成程序测评报告,原因是gprof通过在atexit()里注册了一个函数来产生结果信息,任何非正常退出都不会执行atexit()的动作,所以不会产生gmon.out文件。如果你的程序是一个不会退出的服务程序,那就只有修改代码来达到目的。如果不想改变程序的运行方式,可以添加一个信号处理函数解决问题(这样对代码修改最少),例如: 
  static void sighandler( int sig_no ) 
  { 
  exit(0); 
  } 
  signal( SIGUSR1, sighandler ); 
  当使用kill -USR1 pid 后,程序退出,生成gmon.out文件。 

 

四、GProfile举例


#include 
<stdio.h> 

  
int ppp(int a) 

  


     
int i, b; 

     b 
= 0

     
for(i = 0; i<1000000; i++

        b
++

     }
 

     
return 0

  }
 

 


  
int prime(int n) 

  


     
int i, j, b; 

     b 
= 0

     
for(i=2; i<n; i++

         
for(j = 0; j<1000000; j++

              b
++

         }
 

         
if(n%== 0

           
return 0

         
return 1

        }
 

   }
 

  


   
int main(void

   


      
int i, n; 

      n 
= 1000

      
for(i=2; i<=n; i++

         
if(prime(i)) 

            ppp(i); 

         }
 

      }
 

      
return 0

   }
 

编译程序:gcc -pg -o test test.c
  运行源程序./test后会生成一个gmon.out的文件
   分析结果:gprof -b test gmon.out
 

  

 

 五、GProfile对于结果的分析

      -b 不再输出统计图表中每个字段的详细描述。 
  -p 只输出函数的调用图(Call graph的那部分信息)。 
  -q 只输出函数的时间消耗列表。 
  -e Name 不再输出函数Name 及其子函数的调用图(除非它们有未被限制的其它父函数)。可以给定多个 -e 标志。一个 -e 标志只能指定一个函数。 
  -E Name 不再输出函数Name 及其子函数的调用图,此标志类似于 -e 标志,但它在总时间和百分比时间的计算中排除了由函数Name 及其子函数所用的时间。 
  -f Name 输出函数Name 及其子函数的调用图。可以指定多个 -f 标志。一个 -f 标志只能指定一个函数。 
  -F Name 输出函数Name 及其子函数的调用图,它类似于 -f 标志,但它在总时间和百分比时间计算中仅使用所打印的例程的时间。可以指定多个 -F 标志。一个 -F 标志只能指定一个函数。-F 标志覆盖 -E 标志。 
  -z 显示使用次数为零的例程(按照调用计数和累积时间计算)。 

      GProfile的详细请参考:http://www.cs.utah.edu/dept/old/texinfo/as/gprof.html

      这个文档对GProfile说的很详细,很好。


posted @ 2012-10-26 15:41 jackdong 阅读(1090) | 评论 (0)编辑 收藏

查看系统信息 
cat /proc/cpuinfo - CPU (i.e. vendor, Mhz, flags like mmx) 
cat /proc/interrupts - 中断 
cat /proc/ioports - 设备IO端口 
cat /proc/meminfo - 内存信息(i.e. mem used, free, swap size) 
cat /proc/partitions - 所有设备的所有分区 
cat /proc/pci - PCI设备的信息 
cat /proc/swaps - 所有Swap分区的信息 
cat /proc/version - Linux的版本号 相当于 uname -r 
uname -a - 看系统内核等信息 (1) 处理器使用率 
(2) 内存使用率 
(3) 流入流出数据包 
(4) 整体网络负载 
这些数据分别要从/proc/stat、/proc/net/dev、/proc/meminfo三个文件中提取。如里有问题或对要提取的数据不太清楚,可以使用man proc来查看proc文件系统的联机手册。 
(1) 处理器使用率 
这里要从/proc/stat中提取四个数据:用户模式(user)、低优先级的用户模式(nice)、内核模式(system)以及空闲的处理器时间(idle)。它们均位于/proc/stat文件的第一行。CPU的利用率使用如下公式来计算。 
CPU利用率 = 100 *(user + nice + system)/(user + nice + system + idle) 
(2) 内存使用率 
这里需要从/proc/meminfo文件中提取两个数据,当前内存的使用量(cmem)以及内存总量(amem)。 
内存使用百分比 = 100 * (cmem / umem) 
(3)网络利用率 
为了得到网络利用率的相关数据,需要从/proc/net/dev文件中获得两个数据:从本机输出的数据包数,流入本机的数据包数。它们都位于这个文件的第四行。 
性能收集程序开始记录下这两个数据的初始值,以后每次获得这个值后均减去这个初始值即为从集群启动开始从本节点通过的数据包。 
利用上述数据计算出网络的平均负载,方法如下: 
平 均网络负载 = (输出的数据包+流入的数据包) / 2 获取cpu和内存的还有2种方 法:1)toptop -n 1 -p [pid1,pid2,,,] >>topinfo.txt打开topinfo.txt就能获取进程 的内存cpu信息。2)psps -aux|grep [pid name]|grep -v grep获取到进程的内存cpu信息,其信息更加精练。  从以上来看,由于多线程程序cpu切换是与进程一样,因此无法体现真实的cpu使用率,要将上面方法综合使用才能获取到真实合理的系统信息。
posted @ 2012-10-24 23:12 jackdong 阅读(908) | 评论 (0)编辑 收藏

top 命令详解

版权声明:可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2006/08/16/top-command/以及本声明。

top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器。下面详细介绍它的使用方法。


认识top的显示结果

top命令的显示结果如下所示:

top - 01:06:48 up 1:22, 1 user, load average: 0.06, 0.60, 0.48
Tasks: 29 total, 1 running, 28 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.3% us, 1.0% sy, 0.0% ni, 98.7% id, 0.0% wa, 0.0% hi, 0.0% si
Mem: 191272k total, 173656k used, 17616k free, 22052k buffers
Swap: 192772k total, 0k used, 192772k free, 123988k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1379 root 16 0 7976 2456 1980 S 0.7 1.3 0:11.03 sshd
14704 root 16 0 2128 980 796 R 0.7 0.5 0:02.72 top
1 root 16 0 1992 632 544 S 0.0 0.3 0:00.90 init
2 root 34 19 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0
3 root RT 0 0 0 0 S 0.0 0.0 0:00.00 watchdog/0统计信息区

前五行是系统整体的统计信息。第一行是任务队列信息,同 uptime 命令的执行结果。其内容如下:

01:06:48 当前时间 up 1:22 系统运行时间,格式为时:分 1 user 当前登录用户数 load average: 0.06, 0.60, 0.48 系统负载,即任务队列的平均长度。
三个数值分别为 1分钟、5分钟、15分钟前到现在的平均值。

第二、三行为进程和CPU的信息。当有多个CPU时,这些内容可能会超过两行。内容如下:

Tasks: 29 total 进程总数 1 running 正在运行的进程数 28 sleeping 睡眠的进程数 0 stopped 停止的进程数 0 zombie 僵尸进程数 Cpu(s): 0.3% us 用户空间占用CPU百分比 1.0% sy 内核空间占用CPU百分比 0.0% ni 用户进程空间内改变过优先级的进程占用CPU百分比 98.7% id 空闲CPU百分比 0.0% wa 等待输入输出的CPU时间百分比 0.0% hi 0.0% si

最后两行为内存信息。内容如下:

Mem: 191272k total 物理内存总量 173656k used 使用的物理内存总量 17616k free 空闲内存总量 22052k buffers 用作内核缓存的内存量 Swap: 192772k total 交换区总量 0k used 使用的交换区总量 192772k free 空闲交换区总量 123988k cached 缓冲的交换区总量。
内存中的内容被换出到交换区,而后又被换入到内存,但使用过的交换区尚未被覆盖,
该数值即为这些内容已存在于内存中的交换区的大小。
相应的内存再次被换出时可不必再对交换区写入。 进程信息区

统计信息区域的下方显示了各个进程的详细信息。首先来认识一下各列的含义。

序号 列名 含义 a PID 进程id b PPID 父进程id c RUSER Real user name d UID 进程所有者的用户id e USER 进程所有者的用户名 f GROUP 进程所有者的组名 g TTY 启动进程的终端名。不是从终端启动的进程则显示为 ? h PR 优先级 i NI nice值。负值表示高优先级,正值表示低优先级 j P 最后使用的CPU,仅在多CPU环境下有意义 k %CPU 上次更新到现在的CPU时间占用百分比 l TIME 进程使用的CPU时间总计,单位秒 m TIME+ 进程使用的CPU时间总计,单位1/100秒 n %MEM 进程使用的物理内存百分比 o VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES p SWAP 进程使用的虚拟内存中,被换出的大小,单位kb。 q RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA r CODE 可执行代码占用的物理内存大小,单位kb s DATA 可执行代码以外的部分(数据段+栈)占用的物理内 存大小,单位kb t SHR 共享内存大小,单位kb u nFLT 页面错误次数 v nDRT 最后一次写入到现在,被修改过的页面数。 w S 进程状态。
D=不可中断的睡眠状态
R=运行
S=睡眠
T=跟踪/停止
Z= 僵尸进程 x COMMAND 命令名/命令行 y WCHAN 若该进程在睡眠,则显示睡眠中的系统函数名 z Flags 任务标志,参考 sched.h

默认情况下仅显示比较重要的 PID、USER、PR、NI、VIRT、RES、SHR、S、%CPU、%MEM、TIME+、COMMAND 列。可以通过下面的快捷键来更改显示内容。

更改显示内容

通过 f 键可以选择显示的内容。按 f 键之后会显示列的列表,按 a-z 即可显示或隐藏对应的列,最后按回车键确定。

o 键可以改变列的显示顺序。按小写的 a-z 可以将相应的列向右移动,而大写的 A-Z 可以将相应的列向左移动。最后按回车键确定。

按大写的 FO 键,然后按 a-z 可以将进程按照相应的列进行排序。而大写的 R 键可以将当前的排序倒转。

posted @ 2012-10-24 22:43 jackdong 阅读(579) | 评论 (0)编辑 收藏

http://www.cnblogs.com/greatverve/archive/2010/11/19/vc-dll.html

1 用VC创建DLL动态链接库
1.1 创建dll项目

1.2 为dll项目编写源文件

头文件dllDemo.h
extern "C" _declspec(dllexport) int Sum(int a,int b);//加法函数。
extern "C" _declspec(dllexport) int Max(int a, int b);//取较大值函数
extern "C" _declspec(dllexport) int Min(int a, int b);//取较小值函数
源文件dllDemo.cpp
复制代码
大气象
#include "dllDemo.h"
extern "C" _declspec(dllexport)int Sum(int a, int b)
{
return a+b;}
extern "C" _declspec(dllexport)int Max(int a, int b)
{
    
if(a>=b)
        
return a;
    
else
        
return b;
}
extern "C" _declspec(dllexport)int Min(int a, int b)
{
    
if(a>=b)
        
return b;
    
else
        
return a;
}
复制代码

1.3 生成dll文件

编译源文件,如果没有出现错误提示,那么,在项目文件根目录的Debug文件夹内会生成一个dll文件“dllDemo.dll”。

调用
新建了个MFC单对话框项目,
dllDemo.dll”和”dllDemo.lib”文件复制到本项目的Debug目录下,
在VC工作空间的文件视图下面将”dllDemo.lib”添加到项目中

在对话框头文件添加引用:

复制代码
大气象
// FileOperDlg.h : 头文件
//

#pragma once

extern "C"_declspec(dllimport) int Sum(int a,int b);
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
// CFileOperDlg 对话框
class CFileOperDlg : public CDialog
{
// 构造
public:
    CFileOperDlg(CWnd
* pParent = NULL);    // 标准构造函数

// 对话框数据
    enum { IDD = IDD_FILEOPER_DIALOG };

    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 实现
protected:
    HICON m_hIcon;

    
// 生成的消息映射函数
    virtual BOOL OnInitDialog();
    afx_msg 
void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg 
void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    CString m_info;
};
复制代码

 

调用:

CString str;
int c=Sum(4,5);  
//c=Max(5,6);  
//c=Min(5,6);
str.Format("%d",c);
AfxMessageBox(str);

 

调试
直接运行,选择一个调用dll的exe确定之后,就可以调试了,设置个断点试试。

 

 

 

参考:

VC++的DLL应用(含Demo演示)

作者:一点一滴的Beer http://beer.cnblogs.com/

      在大学大一的时候学的是C,然后后来大二的时候专业又开了C++这个课程,然后再后来自己又自学了一点VC++,大三的时候也试着编写过一个MFC的最简单的窗口程序。到大四的时候,自己又做了一个GIS的项目,是用C#.NET来编写的,然后发现C#上手好容易,而且还大部分语法规则都沿用了C,C++的习惯,于是觉得C++实在是没有一点优势可言啊。但这个暑假的实习经历又改变了我的观点:C++在写窗口程序虽然麻烦,但是却什么能做,而且对比C#来说,对运行环境的要求不高,不用像C#程序在安装之前还要安装100M多的运行.NET环境。C++和C#各有优缺,目前我对它们俩的定位是:C++用来写一些底层的程序,比如驱动,或者是一些算法类型的函数接口,然后用C#来调用这些接口并进行界面设计。如何函数的实现跨语言呢?显然DLL是个很重要的内容,故在此对VC++的DLL模块进行介绍。

1 用VC创建DLL动态连接库

 

1.1 创建dll项目

clip_image002

然后选择“一个空的dll工程”,然后点击“确定”便完成了“创建dll项目”的流程。

 

1.2 为dll项目编写源文件

新建两个文件:dllDemo.h, dllDemo.cpp

在头文件”dllDemo.h”中声明三个接口函数:

extern "C" _declspec(dllexport) int Sum(int a,int b);//加法函数。
extern "C" _declspec(dllexport) int Max(int a, int b);//取较大值函数
extern "C" _declspec(dllexport) int Min(int a, int b);//取较小值函数

 

然后在“dllDemo.cpp”文件中实现三个接口函数:

 

复制代码
#include "dllDemo.h"
extern "C" _declspec(dllexport)int Sum(int a, int b)
{
return a+b;
}
extern "C" _declspec(dllexport)int Max(int a, int b)
{
if(a>=b)return a;
else
return b;
}
extern "C" _declspec(dllexport)int Min(int a, int b)
{
if(a>=b)return b;
else
return a;
}
复制代码

 

 

1.3 生成dll文件

编译源文件,如果没有出现错误提示,那么,在项目文件根目录的Debug文件夹内会生成一个dll文件“dllDemo.dll”。

 

 

2 DLL调用

 

2.1 用C++调用显式链接

clip_image004

新建一个Win32的控制台程序进行显式调用:

1. 新建“dllConsoleEvident”的Win32控制台程序项目

2. 新建cpp文件“dllConsoleEvident.cpp”

3. 将在第一节中,在Debug目录下编译生成的“dllDemo.dll”(显式调用时只需要这一个文件就够了)文件复制到“dllConsoleEvident”项目下的Debug文件夹根目录下

4. 在“dllConsoleEvident.cpp”文件中编写以下代码对dll中的函数进行显式调用

 

复制代码
代码
//////////////////////////////////////////////////////////////////////////
//动态加载DLL文件
#include <iostream.h>
#include
<windows.h>
void main(void)
{
typedef
int(*pMax)(int a,int b);//函数指针
typedef int(*pMin)(int a,int b);
pMax Max
=NULL;
pMin Min
=NULL;
HINSTANCE hDLL;
hDLL
=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;
Max=(pMax)GetProcAddress(hDLL,"Max");
Min
=(pMin)GetProcAddress(hDLL,"Min");
if (Max)//如果取出函数成功,则执行下面的语句
{
int A=Max(5,8);
cout
<<"比较的结果为"<<A;
}
if (Min)
{
int B=Min(5,8);
cout
<<"比较的结果为"<<B;
}
FreeLibrary(hDLL);
//卸载MyDll.dll文件;
}
复制代码

 

 

 

2.2 用C++隐式链接(Win32控制台程序)

clip_image006

新建一个Win32控制台程序演示静态调用

1. 利用向导新建“dllConsoleStaticDemo”的空工程

2. 将dllDemo.dll”和“dllDemo.lib文件复制到Debug目录下,并在项目中包含“dllDemo.lib”文件(或者),否则会出现dll函数找不到的连接错误

3. 新建“dllConsoleStaticDemo.cpp”文件,并写入如下代码:

 

复制代码
extern "C"_declspec(dllimport) int Sum(int a,int b);
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
#include
<iostream.h>
void main()
{
int c=Sum(4,5);
c
=Max(5,6);
c
=Min(5,6);
cout
<<"Hello,dllConsoleTest~!";
}
复制代码

 

 

 

 

4.通过断点,可以看到dll函数调用成功

这种方式的静态调用的特点是:在程序一开始执行的时候,就将dll文件全部加载到程序中,不会释放。

 

2.3 用C++隐式链接(MFC窗口程序)

clip_image008

新建一个MFC基本对话框窗口程序进行调用:

1. 利用向导建立一个MFC基本对话框

2. 将dllDemo.dll”和”dllDemo.lib”文件复制到本项目的Debug目录下,在VC工作空间的文件视图下面将”dllDemo.lib”添加到项目中

3. 在“dllMfcDemoDlg.h”头文件中的前面对来自外部的dll函数进行声明

 

复制代码
// dllMfcDemoDlg.h : header file
//
#if !defined(AFX_DLLMFCDEMODLG_H__E358B876_D188_48FD_8D83_794309C885A9__INCLUDED_)
#define AFX_DLLMFCDEMODLG_H__E358B876_D188_48FD_8D83_794309C885A9__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CDllMfcDemoDlg dialog
extern "C"_declspec(dllimport) int Sum(int a,int b);
extern "C"_declspec(dllimport) int Max(int a,int b);
extern "C"_declspec(dllimport) int Min(int a,int b);
……
复制代码

 

 

 

 

4.在窗体界面上,双击“确定”按钮,进入到OnOk()的事件响应函数体,编写调用代码:

 

复制代码
void CDllMfcDemoDlg::OnOK()
{
// TODO: Add extra validation here
int c=Sum(4,5);
c
=Max(5,6);
c
=Min(5,6);
CDialog::OnOK();
}
复制代码

 

 

 

通过设置断点单步运行就可以看到dll文件中的函数已经被成功调用了。

 

2.4 用C#跨语言调用

C#控制台程序调用VC++建立一个dll:

clip_image010

1. 用Visual Studio建立一个控制台程序

2. 将“dllDemo.dll”文件复制到项目的Debug目录下面

3. 在“Program.cs”中编写如下代码

 

复制代码
代码
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;//引入dll文件中的函数
namespace ConsoleDllDemo
{
class Program
{
//引入dll文件中的函数
[DllImport("dllDemo.dll")]
private static extern int Sum(int a, int b);
[DllImport(
"dllDemo.dll")]
private static extern int Max(int a, int b);
[DllImport(
"dllDemo.dll")]
private static extern int Min(int a, int b);
static void Main(string[] args)
{
int a = Sum(3, 5);
Console.WriteLine(a);
Console.WriteLine(Max(
5,10));
Console.WriteLine(Min(
12,25));
Console.ReadKey();
//要按键才退出。
}
}
}
复制代码

 

 

 

然后断点单步运行,便可以看到调用函数的结果了。

关于DLL的调用的更详细内容可以参考另外一些文章:

http://dev.firnow.com/course/3_program/c++/cppsl/2008127/97781.html

http://dev.yesky.com/283/2640283_2.shtml

 

3 dll调试方法

在建立了dll项目后,并写好相应的实现代码,点击“运行”,会弹出现在的对话框:

clip_image012

然后浏览,找到一个调用了此dll文件的执行文件“*.exe”文件,然后就可以对dll文件进行断点调试了。

这个“*.exe”文件可以是任何平台的,C++也可以,C也可以,C#也可以,只要这个执行文件调用了dll文件中的函数即可。

如果想更换调试的“*.exe”文件,可以在“工程-》设置”对话框中的“调试”选项卡进行设置,浏览找到用户需要的“*.exe”文件

clip_image014

说明:以VC++环境中调用此dll为例,运行dllDemo项目,然后会调用“*.exe”文件,如果此exe文件含有源文件,而且刚好在源文件的Debug目录下面,那么,可以同时在exe文件的源文件中设置断点,进行dll和调用dll两个程序的联调。(好像跨语言调用的时候不能进行联调,笔者只在C++互相调用的时候联调成功过,但C#调用的时候没有联调成功,这个问题有待解决)

 

 

4. DLL返回数据类型探究

目前写的DLL函数反返回值还仅限于整形,还没有尝试其它特殊类型的返回值。更丰富的返回值类型,还要今后慢慢学习和研究。等回学校了再研究吧。请见后续文章吧。

 

 

附件:

VC_dll_Realse.rar中是VC编写DLL并引用DLL的相关源码文件

CShapr_ConsoleDllDemo.rar中是VS2005编写的C#引用VC编写的DLL函数的相关源码文件

http://files.cnblogs.com/beer/VC_dll_Realese.rar

http://files.cnblogs.com/beer/CSharp_ConsoleDllDemo.rar

------------------------------------------------------------------

posted @ 2012-10-23 14:45 jackdong 阅读(359) | 评论 (0)编辑 收藏

1  高级程序设计语言的实现

2 针对计算机体系结构的优化

   a 并行性

   b 内存层次结构

3  新计算机体系结构的设计

   a RISC

   b 专用体系结构

4 程序翻译

   a 二进制翻译

   b 硬件合成

   c 数据查询解释器

   d 编译然后模拟

5 软件生产率工具

   a 类型检查

   b 边界检查

   c 内存管理工具

posted @ 2012-10-22 12:07 jackdong 阅读(447) | 评论 (0)编辑 收藏

仅列出标题
共10页: 1 2 3 4 5 6 7 8 9 Last