Click here to Skip to main content
15,881,424 members
Articles / Programming Languages / Javascript

Under the Hood Part 5 : JavaScript Application & C++ WinRT Component DLL – WinRT, Windows 8, C++, Metro

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
7 Mar 2012CPOL6 min read 20.7K   6   2
How to create a C++ WinRT Component DLL and access it from a JavaScript application

JavaScript Application Calling WinRT Component DLL

In this part, we will create a C++ WinRT Component DLL and access it from a JavaScript application.

We have developed a C++ WinRT Component DLL & C#.NET application in the following post:

We have seen the compiler generated components for making the C# application access the C++ WinRT component in the following post:

We have seen the packaging and installation process that happens in the background during building and deploying of the applications in the below post:

We have seen the C++ XAML application calling the C++ WinRT Component DLL at:

Generally, in a LOB application, we might have to build a C++ Component DLL to take advantage of the performance of C++ in complex or computationally-intensive operations. The C++ component can access Windows operating system services that are not accessible through the Windows Runtime in the current version. Mostly, to reuse existing code that is already written and tested.

Step 1

Create a Windows Runtime C++ Component DLL

Open Visual Studio 2011 –> File –> New Project –> Go to Installed Templates section –> Visual C++ –>Select WinRT Component DLL and name it as CPPWinRTComponentDll as shown in the following figure.

Image 1

Fig 1: CPPWinRTComponentDll project

Open WinRTComponent.h file and create an Employee class as shown in the following code snippet. The Platform namespace is where C++ defines its classes that are specific Windows Runtime types.

Create a private variables address_ and employeeid_. These are used as backing store to hold the values. We will use get() & set() properties to set or get these values.

C++
private:        
            // Backing store for property address_ & employeeid_.        
            Platform::String^ address_;        
            int employeeid_;

In the public section, add the following code which are properties for the above backing store.

C++
property Platform::String^ Address
{
    Platform::String^ get()
    {
        return  (address_);
    }
}

// Property with custom setter/getter
property int EmployeeId
{
    int get()
    {
        return employeeid_;
    }
    //    ‘set’ accessor is missing its value parameter
    void set(int value)
    {
        if(value <= 0)
        {
            throw ref new Platform::InvalidArgumentException();
            employeeid_ = value;
        }
    }
}

We can also add some trivial get/set property with the compiler generating the backing store.

C++
public:
    // Trivial get/set property with compiler-generated backing store.
    property Platform::String^ Name;

Following is the complete code of the Employee class.

C++
public ref class Employee sealed        
    {        
    private:        
            Platform::String^ address_;        
            int employeeid_;        
                   
            //If i use a stack syntax, i get compilation error        
            //Platform::String address2_;        
            //Error    1    error C3149: ‘Platform::String’ : 
            //cannot use this type here without a top-level ‘^’           
            //c:\projects\cppwinrtcomponentdll with cpp app 
            //string\cppwinrtcomponentdll\winrtcomponent.h           

    public:        
        property Platform::String^ Name;        
        property Platform::String^ Address        
        {        
            Platform::String^ get()        
            {        
                return  (address_);        
            }        
        }        
        property int EmployeeId        
        {        
            int get()        
            {        
                return employeeid_;        
            }        
            //    ‘set’ accessor is missing its value parameter        
            void set(int value)        
            {        
                if(value <= 0)        
                {        
                    throw ref new Platform::InvalidArgumentException();        
                    employeeid_ = value;        
                }        
            }        
        }        
    public:        
        Platform::String^ SayHello()        
        {        
            return "Hello World";        
        }        
    public:        
        int Add(int x, int y)        
        {        
            return x+y;        
        }        
    };

When you code your C++ component, if needed, you can use the regular C++ library and built-in types inside the class code except at the abstract binary interface (ABI) boundary where you are passing data to and from JavaScript. There, use Windows Runtime types and the special syntax that Visual C++ supports for creating and manipulating those types.

You have to make the Employee class as activatable class so that it can be instantiated from another language such as JavaScript. To be consumable from another language such as JavaScript, a component must contain at least one activatable class. If needed, a Windows Runtime component can contain multiple activatable classes as well as additional classes known only internally to the component. Client code creates an instance of the component by using the new keyword just as for any class.

The Employee class must be declared as public ref class sealed. The ref class keywords tell the compiler to create the class as a Windows Runtime compatible type, and the sealed keyword specifies that the class cannot be inherited. A class must be sealed to be consumed by JavaScript.

In the Platform::String^ address_, the ^ operator signifies a handle to a Windows Runtime string type that under the covers is reference-counted and deleted when the count reaches zero. Instances of these types are created by using the ref new keywords. Do not explicitly call delete on these instances.

Types must be passed to and from the public methods as Windows Runtime types. If you use the C++ built-in types such as int, double and so on, the compiler will automatically convert them to the appropriate Windows Runtime type. No such conversion occurs unless you are passing the type across the ABI. Complex types such as Platform::String^ must be specified explicitly.

Step 2

Creating a JavaScript Windows Metro Style Application Project

To create a project in this solution, right-click the solution node in Solution Explorer. and select Add Project > Blank Application. Name it as WinWebApp1.

Image 2

Fig 2: Creating the JavaScript project

Add a reference to the component project.

After you have compiled the C++ project for the first time, you can add it as a project reference in the JavaScript project. Right-click the References node in the JavaScript project, and select Add. When the Add References Manager dialog box appears, click “Solution” to display the available references in the solution. Select “CPPWinRTComponentDll ” in this solution and click on Add button as shown in figure 3; The namespace and all public types and methods are now available to your JavaScript code. You can verify this by experimenting with the Member List or Statement Completion feature in the JavaScript file.

Image 3

Fig 3: Adding reference to the C++ WinRT Component DLL.

Add the HTML markup that invokes JavaScript.

Add the following HTML into the <body> node of the default.html page

HTML
<body>        
    <button id="callwinrt" 
    onclick="CallWinRT()">Call WinRT</button>        
<p></p>        
    <label id ="Label1" 
    style="background-color: grey;">Activation Object Result ->  
    </label><label id ="loaded" 
style="background-color: #51B65A;"></label>        
    <p></p>        
     <label id ="Label2" 
     style="background-color: grey;">Calling Employee::SayHello() method     
     </label><label id ="callmethod" 
style="background-color: #51B65A;"></label>        
    <p></p>        
     <label id ="Label3" 
     style="background-color: grey;" >Getting  Employee.Name Property value    
     </label><label id ="retrievedproperty" 
style="background-color: #51B65A;"></label>        
    <p></p>
</body>

The default.html page appears as follows:

HTML
<!DOCTYPE html>        
<html>        
<head>        
    <meta charset="utf-8" />        
    <title>WinWebApp1</title>        
    <!– WinJS references >        
    <link rel="stylesheet" href="/winjs/css/ui-dark.css" />        
    <script src="/winjs/js/base.js"></script>        
    <script src="/winjs/js/wwaapp.js"></script>        
    <!– WinWebApp1 references >        
    <link rel="stylesheet" href="/css/default.css" />        
    <script src="/js/default.js"></script>        
</head>        
<body>        
    <button id="callwinrt" 
    onclick="CallWinRT()">Call WinRT</button>        
<p></p>        
    <label id ="Label1" 
    style="background-color: grey;">Activation Object Result ->  
    </label><label id ="loaded" 
style="background-color: #51B65A;"></label>        
    <p></p>        
     <label id ="Label2" 
     style="background-color: grey;">Calling Employee::SayHello() method     
     </label><label id ="callmethod" 
style="background-color: #51B65A;"></label>        
    <p></p>        
     <label id ="Label3" 
     style="background-color: grey;" >Getting  Employee.Name Property value    
     </label><label id ="retrievedproperty" 
style="background-color: #51B65A;"></label>        
    <p></p>
</body>          
</html>

Add the JavaScript event handlers that call into the component DLL.

Add the following function CallWinRT() at the end of the default.js file. This function is called when you click the button “Call WinRT” on the main page. Notice how JavaScript activates the C++ class, and then calls its methods and populates the HTML labels with the return values.

C++
function CallWinRT() {        
    // activate the native Windows Runtime component        
    var nativeObject = new CppWinRTComponentDll.Employee();        
    document.getElementById(‘loaded’).innerHTML = nativeObject;        

    //call a method        
    var num = nativeObject.sayHello();        
    document.getElementById(‘callmethod’).innerHTML = num;        
    nativeObject.name = "Kishore Babu";        
    // get the value of the string property        
    var propValue = nativeObject.name;        
    document.getElementById(‘retrievedproperty’).innerHTML = propValue;        
}

The complete code of default.js file is as follows:

C++
(function () {        
    ‘use strict’;        
    // Uncomment the following line to enable first chance exceptions.        
    // Debug.enableFirstChanceException(true);        

    WinJS.Application.onmainwindowactivated = function (e) {        
        if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {        
            // TODO: startup code here        
        }        
    }        
    WinJS.Application.start();        
})();        
function CallWinRT() {        
    // activate the native Windows Runtime component        
    var nativeObject = new CppWinRTComponentDll.Employee();        
    document.getElementById(‘loaded’).innerHTML = nativeObject;        
    //call a method        
    var num = nativeObject.sayHello();        
    document.getElementById(‘callmethod’).innerHTML = num;        
    nativeObject.name = "Kishore Babu";        
    // get the value of the string property        
    var propValue = nativeObject.name;        
    document.getElementById(‘retrievedproperty’).innerHTML = propValue;        
}

Build the solution & deploy the application. If you go to start window, you will find an application WinWebApp1. Click on it.

Image 4

Click on call WinRT button. The values from the C++ DLL are returned and set in the JavaScript application as shown in the following figure:

Image 5

When you build a solution that contains a JavaScript project and a Windows Runtime Component DLL project, the JavaScript project files and the compiled DLL are merged into one package, which you can then deploy locally or remotely for testing or submit to the Windows Store. You can also distribute just the component project as an Extension SDK.

Debugging: When you debug a JavaScript solution that has a component DLL, you can set the debugger to enable either stepping through script, or stepping through native code in the component, but not both at the same time. To change the setting, right-click the JavaScript project node in Solution Explorer, then select Properties > Debugging > Debugger Type.

Be sure to select appropriate capabilities in the package designer. For example, if you are attempting to open a file using the Windows Runtime APIs, be sure to select the Document Library Access checkbox in the Capabilities pane of the package designer.

Download the source code here.

As a C++ developer, I find this useful. If you are a C++ developer and new to JavaScript, you sometimes make the mistake of not using the camel-casing in JS. If your JavaScript code does not seem to be recognizing the public properties or methods in the component, make sure that in JavaScript, you are using camel-casing. For example, the Platform::String^ SayHello() C++ method must be referenced as sayHello() in JavaScript.

"The task of the leader is to get his people from where they are to where they have not been." — Henry Kissinger

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Astrani Technology Solutions
United States United States
Kishore Babu Gaddam is a Senior Technology Consultant, Technology Evangelist turned Technology Entrepreneur and a regular speaker at national conferences, regional code camps and local user groups with over 14 years of experience in software product development. His experience includes building & managing award-winning software development teams, managing customer relationships, marketing and launching new software products & services. Kishore launched his technology career almost 15 years ago with a Robotics software development startup and has served in multiple roles since including developer, innovation leader, consultant, technology executive and business owner.

A technology specialist in C++, C#, XAML and Azure, he successfully published two applications to Windows store http://bit.ly/WinStoreApp and http://bit.ly/FlagsApp.

Kishore is the author of the popular Microsoft Technologies blog at http://www.kishore1021.wordpress.com/ and his work on Portable Class Library project in Visual Studio 2012– .NET 4.5 was featured on Channel 9 at http://bit.ly/msdnchannel9. Kishore enjoys helping people understand technical concepts that may initially seem complex and perform lot of Research & Development on emerging technologies to help solve some of the toughest customer issues. Kishore spends a lot of time teaching and mentoring developers to learn new technologies and to be better developers. He is a speaker at various code camps around Washington DC area, mainly at Microsoft Technology Center for NOVA code camp (http://bit.ly/novacc12), CMAP Code Camp Fall 2012 (http://bit.ly/novacc12), etc. The majority of his software development experience has centered on Microsoft technologies including MFC, COM, COM+, WCF, WPF, winRT, HTML5, RestAPI and SQL Server. You can follow Kishore on Twitter at www.twitter.com/kishore1021. He can be reached on email at researcherkishore@outlook.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 432084414-Mar-12 12:00
Member 432084414-Mar-12 12:00 
GeneralRe: My vote of 5 Pin
kishore Gaddam19-Mar-12 9:44
kishore Gaddam19-Mar-12 9:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.