Instruções passo a passo: criando um componente de Tempo de Execução do Windows básico em C++ e chamando-o em JavaScript ou C#
Essa explicação passo a passo mostra como criar uma DLL básica de componente do Tempo de Execução do Windows acessível de JavaScript, C# ou Visual Basic. Antes de iniciar esta explicação passo a passo, verifique se você entende conceitos como a interface binária abstrata (ABI) classes de referência e as extensões de componentes Visual C++ que facilitam o trabalho com classes de referência. Para obter mais informações, consulte Criando componentes do Tempo de Execução do Windows em C++ e Referência da linguagem Visual C++ (C++/CX).
Criando a DLL do componente em C++
Neste exemplo, criaremos o projeto do componente primeiro, mas você pode criar o projeto em JavaScript primeiro. A ordem não importa.
Observe que a classe principal do componente contém exemplos de definições de propriedade e de método e uma declaração de evento. Eles são fornecidos apenas para mostrar como é feito. Eles não são necessários e, neste exemplo, substituiremos todo o código gerado pelo nosso próprio código.
Para criar o projeto de componente C++
Na barra de menus do Visual Studio, escolha Arquivo, Novo, Projeto.
Na caixa de diálogo Novo Projeto, no painel esquerdo, expanda Visual C++ e selecione o nó de aplicativos Windows Store.
No painel central, selecione Componente do Tempo de Execução do Windows e nomeie o projeto como WinRT_CPP.
Escolha o botão OK.
Para adicionar uma classe ativável ao componente
- Uma classe ativável é uma que o código cliente pode criar usando uma expressão new (New em Visual Basic ou ref new em C++). No seu componente, declare-o como public ref class sealed. Na verdade, os arquivos Class1.h e .cpp já têm uma classe de referência. Você pode alterar o nome, mas nesse exemplo, usaremos o nome padrão Class1. Você pode definir classes de referência adicionais ou classes regulares em seu componente, caso sejam necessárias. Para obter mais informações sobre as classes ref, consulte Sistema de tipos (C++/CX).
Para adicionar as diretivas #include necessárias
Adicione estas políticas de #include à Class1.h:
#include <collection.h> #include <amp.h> #include <amp_math.h>
collection.h é o arquivo de cabeçalho para classes concretas C++, como Classe Platform::Collections::Vector e Classe Platform::Collections::Map, que implementam as interfaces de linguagem neutra que são definidas pelo Tempo de Execução do Windows. Os cabeçalhos amp são usados para executar cálculos na GPU. Eles não têm equivalentes do Tempo de Execução do Windows, e isso é bom porque são particulares. Em geral, por motivos de desempenho, você deve usar bibliotecas padrão e de código ISO C++ internamente no componente; é apenas a interface do Tempo de Execução do Windows que deve ser expressa em tipos do Tempo de Execução do Windows.
Para adicionar um delegado no escopo do namespace
Um delegado é uma construção que define os parâmetros e o tipo de retorno para métodos. Um evento é uma instância de um tipo específico de delegado, e qualquer método manipulador de eventos que assinar o evento deverá ter a assinatura que é especificada no delegado. O código a seguir define um tipo de delegado que utiliza um int e retorna void. Em seguida, o código declara um event público desse tipo, o que permite que o código cliente forneça métodos que são invocados quando o evento é acionado.
Adicione a declaração de delegado a seguir no escopo do namespace em Class1.h, exatamente antes da declaração Class1.
public delegate void PrimeFoundHandler(int result);
Dica
Se o código não for alinhado corretamente quando você o colar no Visual Studio, basta pressionar Ctrl+K+D para corrigir o recuo do arquivo inteiro.
Para adicionar os membros públicos
A classe expõe três métodos públicos e um evento público. O primeiro método é síncrono porque sempre é executado muito rápido. Como os outros dois métodos podem levar algum tempo, eles são assíncronos, de modo que não bloqueiam o thread de interface do usuário. Esses métodos retornam IAsyncOperationWithProgress e IAsyncActionWithProgress. O primeiro define um método assíncrono que retorna um resultado, e o segundo define um método assíncrono que retorna void. Essas interfaces também permitem que o código cliente receba atualizações durante o progresso da operação.
public: // Synchronous method. Windows::Foundation::Collections::IVector<double>^ ComputeResult(double input); // Asynchronous methods Windows::Foundation::IAsyncOperationWithProgress<Windows::Foundation::Collections::IVector<int>^, double>^ GetPrimesOrdered(int first, int last); Windows::Foundation::IAsyncActionWithProgress<double>^ GetPrimesUnordered(int first, int last); // Event whose type is a delegate "class" event PrimeFoundHandler^ primeFoundEvent;
Para adicionar os membros particulares
A classe contém três membros particulares: dois métodos auxiliares para os cálculos numéricos e um objeto CoreDispatcher que é usado para realizar marshaling das invocações de eventos dos threads de trabalho para o thread de interface do usuário.
private: bool is_prime(int n); Windows::UI::Core::CoreDispatcher^ m_dispatcher;
Para adicionar as diretivas de cabeçalho e namespace
Em Class1.cpp, adicione estas diretivas #include:
#include <ppltasks.h> #include <concurrent_vector.h>
Agora adicione estas instruções using para efetuar pull nos namespaces necessários:
using namespace concurrency; using namespace Platform::Collections; using namespace Windows::Foundation::Collections; using namespace Windows::Foundation; using namespace Windows::UI::Core;
Para adicionar a implementação para ComputeResult
Em Class1.cpp, adicione a implementação do método a seguir. Esse método é executado de modo síncrono no thread de chamada, mas é muito rápido porque usa C++ AMP para paralelizar a computação na GPU. Para obter mais informações, consulte Visão geral do C++ AMP. Os resultados são anexados a um tipo concreto Platform::Collections::Vector<T>, que é convertido implicitamente em um Windows::Foundation::Collections::IVector<T> quando é retornado.
//Public API IVector<double>^ Class1::ComputeResult(double input) { // Implement your function in ISO C++ or // call into your C++ lib or DLL here. This example uses AMP. float numbers[] = { 1.0, 10.0, 60.0, 100.0, 600.0, 10000.0 }; array_view<float, 1> logs(6, numbers); // See https://msdn.microsoft.com/en-us/library/hh305254.aspx parallel_for_each( logs.extent, [=] (index<1> idx) restrict(amp) { logs[idx] = concurrency::fast_math::log10(logs[idx]); } ); // Return a Windows Runtime-compatible type across the ABI auto res = ref new Vector<double>(); int len = safe_cast<int>(logs.extent.size()); for(int i = 0; i < len; i++) { res->Append(logs[i]); } // res is implicitly cast to IVector<double> return res; }
Para adicionar a implementação para GetPrimesOrdered e seu método auxiliar
Em Class1.cpp, adicione as implementações de GetPrimesOrdered e o método auxiliar de is_prime. GetPrimesOrdered usa Classe concurrent_vector e um loop de Função parallel_for para dividir o trabalho e usar os recursos máximos do computador no qual o programa estiver sendo executado para produzir resultados. Depois que os resultados são computados, armazenados e classificados, eles são adicionados a um Platform::Collections::Vector<T> e retornados como Windows::Foundation::Collections::IVector<T> ao código cliente.
Observe o código do relator de progresso, que permite que o cliente vincule uma barra de progresso ou outra interface de usuário para mostrar ao usuário quanto tempo a operação ainda vai demorar. O relatório de progresso tem um custo. Um evento deve ser acionado no lado do componente e manipulado no thread de interface do usuário, e o valor de progresso deve ser armazenado em cada iteração. Uma forma de minimizar o custo é limitar a frequência com que um evento de progresso é acionado. Se o custo ainda for proibitivo, ou se você não puder estimar a duração da operação, considere usar um anel de progresso, que mostra que uma operação está em andamento mas não mostra o tempo restante até a conclusão.
// Determines whether the input value is prime. bool Class1::is_prime(int n) { if (n < 2) return false; for (int i = 2; i < n; ++i) { if ((n % i) == 0) return false; } return true; } // This method computes all primes, orders them, then returns the ordered results. IAsyncOperationWithProgress<IVector<int>^, double>^ Class1::GetPrimesOrdered(int first, int last) { return create_async([this, first, last] (progress_reporter<double> reporter) -> IVector<int>^ { // Ensure that the input values are in range. if (first < 0 || last < 0) { throw ref new InvalidArgumentException(); } // Perform the computation in parallel. concurrent_vector<int> primes; long operation = 0; long range = last - first + 1; double lastPercent = 0.0; parallel_for(first, last + 1, [this, &primes, &operation, range, &lastPercent, reporter](int n) { // Increment and store the number of times the parallel // loop has been called on all threads combined. There // is a performance cost to maintaining a count, and // passing the delegate back to the UI thread, but it's // necessary if we want to display a determinate progress // bar that goes from 0 to 100%. We can avoid the cost by // setting the ProgressBar IsDeterminate property to false // or by using a ProgressRing. if(InterlockedIncrement(&operation) % 100 == 0) { reporter.report(100.0 * operation / range); } // If the value is prime, add it to the local vector. if (is_prime(n)) { primes.push_back(n); } }); // Sort the results. std::sort(begin(primes), end(primes), std::less<int>()); reporter.report(100.0); // Copy the results to a Vector object, which is // implicitly converted to the IVector return type. IVector // makes collections of data available to other // Windows Runtime components. return ref new Vector<int>(primes.begin(), primes.end()); }); }
Para adicionar a implementação para GetPrimesUnordered
A última etapa para criar o componente C++ é adicionar a implementação para GetPrimesUnordered em Class1.cpp. Esse método retorna cada resultado como ele é encontrado, sem esperar até que todos os resultados sejam localizados. Cada resultado é retornado no manipulador de eventos e exibido na interface do usuário em tempo real. Novamente, observe que é usado um relator de progresso. Esse método também usa o método auxiliar is_prime.
// This method returns no value. Instead, it fires an event each time a // prime is found, and passes the prime through the event. // It also passes progress info. IAsyncActionWithProgress<double>^ Class1::GetPrimesUnordered(int first, int last) { auto window = Windows::UI::Core::CoreWindow::GetForCurrentThread(); m_dispatcher = window->Dispatcher; return create_async([this, first, last](progress_reporter<double> reporter) { // Ensure that the input values are in range. if (first < 0 || last < 0) { throw ref new InvalidArgumentException(); } // In this particular example, we don't actually use this to store // results since we pass results one at a time directly back to // UI as they are found. However, we have to provide this variable // as a parameter to parallel_for. concurrent_vector<int> primes; long operation = 0; long range = last - first + 1; double lastPercent = 0.0; // Perform the computation in parallel. parallel_for(first, last + 1, [this, &primes, &operation, range, &lastPercent, reporter](int n) { // Store the number of times the parallel loop has been called // on all threads combined. See comment in previous method. if(InterlockedIncrement(&operation) % 100 == 0) { reporter.report(100.0 * operation / range); } // If the value is prime, pass it immediately to the UI thread. if (is_prime(n)) { // Since this code is probably running on a worker // thread, and we are passing the data back to the // UI thread, we have to use a CoreDispatcher object. m_dispatcher->RunAsync( CoreDispatcherPriority::Normal, ref new DispatchedHandler([this, n, operation, range]() { this->primeFoundEvent(n); }, Platform::CallbackContext::Any)); } }); reporter.report(100.0); }); }
Pressione Ctrl+Shift+B para criar o componente.
Criando um aplicativo cliente JavaScript
Para criar um projeto em JavaScript
-
Dica
Se você quiser apenas criar um cliente C#, poderá ignorar esta seção.
No Gerenciador de Soluções, abra o menu de atalho do nó Solução e escolha Adicionar, Novo Projeto.
Expanda JavaScript (pode estar aninhado em Outras Linguagens) e escolha Aplicativo em Branco.
Aceite o nome padrão App1 escolhendo o botão OK.
Abra o menu de atalho do nó de projeto App1 e escolha Definir como Projeto de Inicialização.
Adicione uma referência de projeto a WinRT_CPP:
Abra o menu de atalho do nó Referências e escolha Adicionar Referência.
No painel esquerdo da caixa de diálogo Gerenciador de Referências, selecione Solução e Projetos.
No painel central, selecione WinRT_CPP e escolha o botão OK.
Para adicionar o HTML que invoca manipuladores de eventos JavaScript
Cole este HTML no nó <body> da página default.html:
<div id="LogButtonDiv"> <button id="logButton" onclick="LogButton_Click()">Logarithms using AMP</button> </div> <div id="LogResultDiv"> <p id="logResult"></p> </div> <div id="OrderedPrimeButtonDiv"> <button id="orderedPrimeButton" onclick="ButtonOrdered_Click()">Primes using parallel_for with sort</button> </div> <div id="OrderedPrimeProgress"> <progress id="OrderedPrimesProgressBar" style="-ms-grid-column-span:2" value="0" max="100"></progress> </div> <div id="OrderedPrimeResultDiv"> <p id="orderedPrimes"> Primes found (ordered): </p> </div> <div id="UnorderedPrimeButtonDiv"> <button id="ButtonUnordered" onclick="ButtonUnordered_Click()">Primes returned as they are produced.</button> </div> <div id="UnorderedPrimeDiv"> <progress id="UnorderedPrimesProgressBar" value="0" max="100"></progress> </div> <div id="UnorderedPrime"> <p id="unorderedPrimes"> Primes found (unordered): </p> </div> <div id="ClearDiv"> <button id="Button_Clear" onclick="ButtonClear_Click()">Clear</button> </div>
<div id="LogButtonDiv"> <button id="logButton" onclick="LogButton_Click()">Logarithms using AMP</button> </div> <div id="LogResultDiv"> <p id="logResult"></p> </div> <div id="OrderedPrimeButtonDiv"> <button id="orderedPrimeButton" onclick="ButtonOrdered_Click()">Primes using parallel_for with sort</button> </div> <div id="OrderedPrimeProgress"> <progress id="OrderedPrimesProgressBar" value="0" max="100"></progress> </div> <div id="OrderedPrimeResultDiv"> <p id="orderedPrimes"> Primes found (ordered): </p> </div> <div id="UnorderedPrimeButtonDiv"> <button id="ButtonUnordered" onclick="ButtonUnordered_Click()">Primes returned as they are produced.</button> </div> <div id="UnorderedPrimeDiv"> <progress id="UnorderedPrimesProgressBar" value="0" max="100"></progress> </div> <div id="UnorderedPrime"> <p id="unorderedPrimes"> Primes found (unordered): </p> </div> <div id="ClearDiv"> <button id="Button_Clear" onclick="ButtonClear_Click()">Clear</button> </div>
Para adicionar estilos
Em default.css, remova o estilo body e adicione estes estilos:
#LogButtonDiv { border: orange solid 1px; -ms-grid-row: 1; /* default is 1 */ -ms-grid-column: 1; /* default is 1 */ } #LogResultDiv { background: black; border: red solid 1px; -ms-grid-row: 1; -ms-grid-column: 2; } #UnorderedPrimeButtonDiv, #OrderedPrimeButtonDiv { border: orange solid 1px; -ms-grid-row: 2; -ms-grid-column:1; } #UnorderedPrimeProgress, #OrderedPrimeProgress { border: red solid 1px; -ms-grid-column-span: 2; height: 40px; } #UnorderedPrimeResult, #OrderedPrimeResult { border: red solid 1px; font-size:smaller; -ms-grid-row: 2; -ms-grid-column: 3; -ms-overflow-style:scrollbar; }
Para adicionar manipuladores de eventos JavaScript que chamam a DLL do componente
Adicione as seguintes funções ao final do arquivo default.js. Essas funções são chamadas quando os botões na página principal são escolhidos. Observe como o JavaScript ativa a classe C++ e, em seguida, chama seus métodos e usa os valores de retorno para preencher os rótulos HTML.
var nativeObject = new WinRT_CPP.Class1(); function LogButton_Click() { var val = nativeObject.computeResult(0); var result = ""; for (i = 0; i < val.length; i++) { result += val[i] + "<br/>"; } document.getElementById('logResult').innerHTML = result; } function ButtonOrdered_Click() { document.getElementById('orderedPrimes').innerHTML = "Primes found (ordered): "; nativeObject.getPrimesOrdered(2, 10000).then( function (v) { for (var i = 0; i < v.length; i++) document.getElementById('orderedPrimes').innerHTML += v[i] + " "; }, function (error) { document.getElementById('orderedPrimes').innerHTML += " " + error.description; }, function (p) { var progressBar = document.getElementById("OrderedPrimesProgressBar"); progressBar.value = p; }); } function ButtonUnordered_Click() { document.getElementById('unorderedPrimes').innerHTML = "Primes found (unordered): "; nativeObject.onprimefoundevent = handler_unordered; nativeObject.getPrimesUnordered(2, 10000).then( function () { }, function (error) { document.getElementById("unorderedPrimes").innerHTML += " " + error.description; }, function (p) { var progressBar = document.getElementById("UnorderedPrimesProgressBar"); progressBar.value = p; }); } var handler_unordered = function (n) { document.getElementById('unorderedPrimes').innerHTML += n.target.toString() + " "; }; function ButtonClear_Click() { document.getElementById('logResult').innerHTML = ""; document.getElementById("unorderedPrimes").innerHTML = ""; document.getElementById('orderedPrimes').innerHTML = ""; document.getElementById("UnorderedPrimesProgressBar").value = 0; document.getElementById("OrderedPrimesProgressBar").value = 0; }
var nativeObject = new WinRT_CPP.Class1(); function LogButton_Click() { var val = nativeObject.computeResult(0); var result = ""; for (i = 0; i < val.length; i++) { result += val[i] + "<br/>"; } document.getElementById('logResult').innerHTML = result; } function ButtonOrdered_Click() { document.getElementById('orderedPrimes').innerHTML = "Primes found (ordered): "; nativeObject.getPrimesOrdered(2, 10000).then( function (v) { for (var i = 0; i < v.length; i++) document.getElementById('orderedPrimes').innerHTML += v[i] + " "; }, function (error) { document.getElementById('orderedPrimes').innerHTML += " " + error.description; }, function (p) { var progressBar = document.getElementById("OrderedPrimesProgressBar"); progressBar.value = p; }); } function ButtonUnordered_Click() { document.getElementById('unorderedPrimes').innerHTML = "Primes found (unordered): "; nativeObject.onprimefoundevent = handler_unordered; nativeObject.getPrimesUnordered(2, 10000).then( function () { }, function (error) { document.getElementById("unorderedPrimes").innerHTML += " " + error.description; }, function (p) { var progressBar = document.getElementById("UnorderedPrimesProgressBar"); progressBar.value = p; }); } var handler_unordered = function (n) { document.getElementById('unorderedPrimes').innerHTML += n.target.toString() + " "; }; function ButtonClear_Click() { document.getElementById('logResult').innerHTML = ""; document.getElementById("unorderedPrimes").innerHTML = ""; document.getElementById('orderedPrimes').innerHTML = ""; document.getElementById("UnorderedPrimesProgressBar").value = 0; document.getElementById("OrderedPrimesProgressBar").value = 0; }
Pressione F5 para executar o aplicativo.
Criando um aplicativo cliente C#
A DLL do componente do Tempo de Execução do Windows C++ pode ser tão facilmente ser chamada de um cliente C# quanto de um cliente JavaScript. As etapas a seguir mostram como criar um cliente C# que seja aproximadamente equivalente ao cliente JavaScript na seção anterior.
Para criar um projeto C#
No Gerenciador de Soluções, abra o menu de atalho do nó Solução e escolha Adicionar, Novo Projeto.
Expanda Visual C# (pode estar aninhado em Outras Linguagens), selecione Windows Store no painel esquerdo e selecione Aplicativo em Branco no painel do meio.
Nomeie o aplicativo como CS_Client e escolha o botão OK.
Abra o menu de atalho do nó de projeto CS_Client e escolha Definir como Projeto de Inicialização.
Adicione uma referência de projeto a WinRT_CPP:
Abra o menu de atalho do nó Referências e escolha Adicionar Referência.
No painel esquerdo da caixa de diálogo Gerenciador de Referências, selecione Solução e Projetos.
No painel central, selecione WinRT_CPP e escolha o botão OK.
Para adicionar o XAML que define a interface do usuário
Adicione o seguinte ScrollViewer e seu conteúdo à Grade em mainpage.xaml:
<ScrollViewer> <StackPanel Width="1400"> <Button x:Name="Button1" Width="340" Height="50" Margin="0,20,20,20" Content="Synchronous Logarithm Calculation" FontSize="16" Click="Button1_Click_1"/> <TextBlock x:Name="Result1" Height="100" FontSize="14"></TextBlock> <Button x:Name="PrimesOrderedButton" Content="Prime Numbers Ordered" FontSize="16" Width="340" Height="50" Margin="0,20,20,20" Click="PrimesOrderedButton_Click_1"></Button> <ProgressBar x:Name="PrimesOrderedProgress" IsIndeterminate="false" Height="40"></ProgressBar> <TextBlock x:Name="PrimesOrderedResult" MinHeight="100" FontSize="10" TextWrapping="Wrap"></TextBlock> <Button x:Name="PrimesUnOrderedButton" Width="340" Height="50" Margin="0,20,20,20" Click="PrimesUnOrderedButton_Click_1" Content="Prime Numbers Unordered" FontSize="16"></Button> <ProgressBar x:Name="PrimesUnOrderedProgress" IsIndeterminate="false" Height="40" ></ProgressBar> <TextBlock x:Name="PrimesUnOrderedResult" MinHeight="100" FontSize="10" TextWrapping="Wrap"></TextBlock> <Button x:Name="Clear_Button" Content="Clear" HorizontalAlignment="Left" Margin="0,20,20,20" VerticalAlignment="Top" Width="341" Click="Clear_Button_Click" FontSize="16"/> </StackPanel> </ScrollViewer>
Para adicionar manipuladores de eventos para os botões
No Gerenciador de Soluções, abra mainpage.xaml.cs. (O arquivo pode estar aninhado em mainpage.xaml.) Adicione uma diretiva using para System.Text e, em seguida, adicione o manipulador de eventos para o cálculo do logaritmo na classe MainPage, logo após OnNavigateTo.
private void Button1_Click_1(object sender, RoutedEventArgs e) { // Create the object var nativeObject = new WinRT_CPP.Class1(); // Call the synchronous method. val is an IList that // contains the results. var val = nativeObject.ComputeResult(0); StringBuilder result = new StringBuilder(); foreach (var v in val) { result.Append(v).Append(System.Environment.NewLine); } this.Result1.Text = result.ToString(); }
Adicione o manipulador de eventos para o resultado ordenado.
async private void PrimesOrderedButton_Click_1(object sender, RoutedEventArgs e) { var nativeObject = new WinRT_CPP.Class1(); StringBuilder sb = new StringBuilder(); sb.Append("Primes found (ordered): "); PrimesOrderedResult.Text = sb.ToString(); // Call the asynchronous method var asyncOp = nativeObject.GetPrimesOrdered(2, 100000); // Before awaiting, provide a lambda or named method // to handle the Progress event that is fired at regular // intervals by the asyncOp object. This handler updates // the progress bar in the UI. asyncOp.Progress = (asyncInfo, progress) => { PrimesOrderedProgress.Value = progress; }; // Wait for the operation to complete var asyncResult = await asyncOp; // Convert the results to strings foreach (var result in asyncResult) { sb.Append(result).Append(" "); } // Display the results PrimesOrderedResult.Text = sb.ToString(); }
Adicione o manipulador de eventos para o resultado não ordenado e para o botão que limpa os resultados, de modo que você possa executar o código novamente.
private void PrimesUnOrderedButton_Click_1(object sender, RoutedEventArgs e) { var nativeObject = new WinRT_CPP.Class1(); StringBuilder sb = new StringBuilder(); sb.Append("Primes found (unordered): "); PrimesUnOrderedResult.Text = sb.ToString(); // primeFoundEvent is a user-defined event in nativeObject // It passes the results back to this thread as they are produced // and the event handler that we define here immediately displays them. nativeObject.primeFoundEvent += (n) => { sb.Append(n.ToString()).Append(" "); PrimesUnOrderedResult.Text = sb.ToString(); }; // Call the async method. var asyncResult = nativeObject.GetPrimesUnordered(2, 100000); // Provide a handler for the Progress event that the asyncResult // object fires at regular intervals. This handler updates the progress bar. asyncResult.Progress += (asyncInfo, progress) => { PrimesUnOrderedProgress.Value = progress; }; } private void Clear_Button_Click(object sender, RoutedEventArgs e) { PrimesOrderedProgress.Value = 0; PrimesUnOrderedProgress.Value = 0; PrimesUnOrderedResult.Text = ""; PrimesOrderedResult.Text = ""; Result1.Text = ""; }
Executando o aplicativo
Selecione o projeto C# ou JavaScript como o projeto de inicialização abrindo o menu de atalho do nó do projeto no Gerenciador de Soluções e selecionando Definir como Projeto de Inicialização. Em seguida, pressione F5 para executar com depuração, ou Ctrl+F5 para executar sem depuração.
Inspecionando seu componente no Pesquisador de Objetos (opcional)
No Pesquisador de Objetos, você pode inspecionar todos os tipos do Tempo de Execução do Windows que são definidos em arquivos .winmd. Isso inclui os tipos no namespace Platform e no namespace padrão. No entanto, como os tipos no namespace Platform::Collections são definidos no arquivo de cabeçalho collections.h, não em um arquivo winmd, eles não aparecem no Pesquisador de Objetos.
Para inspecionar o componente
Na barra de menus, escolha Exibir, Outras Janelas, Pesquisador de Objetos.
No painel esquerdo do Pesquisador de Objetos, expanda o nó WinRT_CPP para mostrar os tipos e métodos definidos no seu componente.
Dicas de depuração
Para obter uma melhor experiência de depuração, baixe os símbolos de depuração dos servidores públicos de símbolos da Microsoft:
Na barra de menus, escolha Ferramentas, Opções.
Na caixa de diálogo Opções, expanda Depuração e selecione Símbolos.
Selecione Servidores de Símbolo da Microsoft e escolha o botão OK.
Pode levar algum tempo para baixar os símbolos na primeira vez. Para melhorar o desempenho na próxima vez que você pressionar F5, especifique um diretório local no qual armazenar os símbolos em cache.
Quando você depura uma solução JavaScript que tem uma DLL de componente, pode definir o depurador para percorrer o script ou o código nativo no componente, mas não ambos ao mesmo tempo. Para alterar a configuração, abra o menu de atalho do nó de projeto em JavaScript no Gerenciador de Soluções e escolha Propriedades, Depuração, Tipo de Depurador.
Certifique-se de selecionar recursos apropriados no designer de pacote. Por exemplo, se você estiver tentando acessar arquivos de forma programática na pasta Imagens, certifique-se de marcar a caixa de seleção Biblioteca de Imagens no painel Recursos do designer de pacote.
Se o seu código JavaScript não reconhecer as propriedades públicas nem os métodos do componente, verifique se você está usando a concatenação com maiúsculas e minúsculas em JavaScript. Por exemplo, o método ComputeResult C++ deve ser referenciado como computeResult em JavaScript.
Se você remover um projeto do Componente C++ do Tempo de Execução do Windows de uma solução, também deverá remover manualmente a referência ao projeto do projeto em JavaScript. Caso contrário, as operações de depuração e compilação subsequentes não serão executadas. Se necessário, você poderá adicionar uma referência a assembly à DLL.
Consulte também
Referência
Roadmap for Windows Store apps using C++
Outros recursos
Desenvolvendo o Bing Maps Trip Optimizer, um aplicativo da Windows Store em JavaScript e C++