WinRT 基础
2012-10-09 10:43
85 查看
This article shows how to use C++ to create a Windows Runtime component, which is a DLL that's callable from a Windows Store app that's built by using JavaScript—or C#, Visual Basic, or C++. Here are several reasons for building such a component:
To get the performance advantage of C++ in complex or computationally intensive operations.
To reuse code that's already written and tested.
When you build a solution that contains a JavaScript or .NET project, and a Windows Runtime component project, the JavaScript project files and the compiled DLL are merged into one package, which you can debug locally in the simulator or remotely on a tethered
device. You can also distribute just the component project as an Extension SDK. For more information, seeHow to: Create a Software Development Kit.
In general, when you code your C++ component, use the regular C++ library and built-in types, except at the abstract binary interface (ABI) boundary where you are passing data to and from code in another .winmd package. There, use Windows Runtime types and
the special syntax that Visual C++ supports for creating and manipulating those types. In addition, in your Visual C++ code, use types such asdelegate and
event to implement events that can be fired from your component and handled in JavaScript, Visual Basic, or C#. For more information about the new Visual C++ syntax, seeVisual
C++ Language Reference (C++/CX).
Casing and naming rules
JavaScript
JavaScript is case-sensitive. Therefore, you must follow these casing conventions:
When you reference C++ namespaces and classes, use the same casing that's used on the C++ side.
When you call methods, use camel casing even if the method name is capitalized on the C++ side. For example, a C++ methodGetDate() must be called from JavaScript as
getDate().
An activatable class name and namespace name can't contain UNICODE characters.
.NET
The .NET languages follow their normal casing rules.
Instantiating the object
Only Windows Runtime types can be passed across the ABI boundary. The compiler will raise an error if the component has a type likestd::wstring as a return type or parameter in a public method. The Visual C++ component extensions (C++/CX)
built-in types include the usual scalars such asint and
double, and also their typedef equivalentsint32,
float64, and so on.For more information, seeType System (C++/CX).
C++
C++
Copy
JavaScript
JScript
Copy
.NET
C#
Copy
C++ built-in types, library types, and Windows Runtime types
An activatable class (also known as a ref class) is one that can be instantiated from another language such as JavaScript, C# or Visual Basic. To be consumable from another language, a component must contain at least one activatable class.
A Windows Runtime component can contain multiple public activatable classes as well as additional classes that are known only internally to the component. All public classes must reside in the same root namespace which has the same name as the component
metadata file. Apply the [WebHostHidden] attribute to C++ types that are not intended to be visible to JavaScript.
Client code creates an instance of the component by using the new (New in Visual Basic) keyword just as for any class.
An activatable class must be declared as public ref class sealed. Theref class keyword tells the compiler to create the class as a Windows Runtime compatible type, and thesealed
keyword specifies that the class cannot be inherited. The Windows Runtime does not currently support a generalized inheritance model; a limited inheritance model supports creation of custom XAML controls. For more information, see
Ref classes and structs (C++/CX).
For C++, all the numeric primitives are defined in the default namespace. The
Platform Namespace contains C++ classes that are specific to the Windows Runtime type system. These includePlatform::String
Class andPlatform::Object Class. The concrete collection types such asPlatform::Collections::Map
Class andPlatform::Collections::Vector Class are defined in thePlatform::Collections
Namespace. The public interfaces that these types implement are defined inWindows::Foundation::Collections Namespace (C++/CX). It is these interface
types that are consumed by JavaScript, C# and Visual Basic. For more information, see
Type System (C++/CX).
C++
C++
Copy
JavaScript
JScript
Copy
.NET
A value struct is a plain old data object that can contain fields which are public by default. Avalue struct is passed by value.
C++
C++
Copy
JavaScript
To pass user-defined value structs across the ABI, define a JavaScript object that has the same members as the value struct that's defined in C++. You can then pass that object as an argument to a C++ method so that the object is implicitly converted to
the C++ type.
JScript
Copy
Another approach is to define a class that implements IPropertySet (not shown).
C#
In the .NET languages, you just create a variable of the type that's defined in the C++ component.
C#
Copy
A C++ public ref class can contain overloaded methods, but JavaScript has limited ability to differentiate overloaded methods. For example, it can tell the difference between these signatures:
C++
Copy
But it can’t tell the difference between these:
C++
Copy
or these:
In ambiguous cases, you can ensure that JavaScript always calls a specific overload by applying theWindows::Foundation::Metadata::DefaultOverload attribute to the method signature in the header file.
This JavaScript always calls the attributed overload:
JScript
Copy
.NET
The .NET languages recognize overloads in a C++ ref class just as in any .NET Framework class.
DateTime
In the Windows Runtime, a Windows::Foundation::DateTime object is just a 64-bit signed integer that represents the number of 100-nanosecond intervals either before or after January 1, 1601. There are no methods on aWindows:Foundation::DateTime
object. Instead, each language projects the DateTime in the way that is native to that language: theDate object in JavaScript and the
System.DateTime andSystem.DateTimeOffset types in the .NET Framework.
C++
C++
Copy
JavaScript
When you pass a DateTime value from C++ to JavaScript, JavaScript accepts it as aDate object and displays it by default as a long-form date string.
JScript
Copy
.NET
When a .NET language passes a System.DateTime to a C++ component, the method accepts it as aWindows::Foundation::DateTime. When the component passes a
Windows::Foundation::DateTime to a .NET Framework method, the Framework method accepts it as aDateTimeOffset.
C#
Copy
Collections and arrays
Collections are always passed across the ABI boundary as handles to Windows Runtime types such asWindows::Foundation::Collections::IVector^ and
Windows::Foundation::Collections::IMap^. For example, if you return a handle to aPlatform::Collections::Map, it implicitly converts to a
Windows::Foundation::Collections::IMap^. The collection interfaces are defined in a namespace that's separate from the C++ classes that provide the concrete implementations. JavaScript and .NET languages consume the interfaces. For more information,
see Collections (C++/CX) andArray and WriteOnlyArray (C++/CX).
C++
C++
Copy
JavaScript
JScript
Copy
.NET
The .NET languages see IVector<T> as IList<T>.
C#
Copy
C++
C++
Copy
JavaScript
JScript
Copy
.NET
The .NET languages see IMap as IDictionary<K,V>.
C#
Copy
Properties
A public ref class in Visual C++ component extensions exposes public data members as properties, by using theproperty keyword. The concept is identical to .NET Framework properties. A trivial property resembles a data
member because its functionality is implicit. A non-trivial property has explicit get and set accessors and a named private variable that's the "backing store" for the value. In this example, the private membervariable _propertyAValue is the
backing store for PropertyA. A property can fire an event when its value changes, and a client app can register to receive that event.
C++
C++
Copy
JavaScript
JScript
Copy
.NET
The .NET languages access properties on a native C++ object just as they would on a .NET Framework object.
C#
Copy
Delegates and events
A delegate is a Windows Runtime type that represents a function object. You can use delegates in connection with events, callbacks, and asynchronous method calls to specify an action to be performed later. Like a function object, the delegate
provides type-safety by enabling the compiler to verify the return type and parameter types of the function. The declaration of a delegate resembles a function signature, the implementation resembles a class definition, and the invocation resembles a function
invocation.
You can use the event keyword to declare a public member of a specified delegate type. Client code subscribes to the event by using the standard mechanisms that are provided in the particular language.
C++
C++
Copy
This example uses the same C++ code as for the previous properties section.
JavaScript
JScript
Copy
.NET
In the .NET languages, subscribing to an event in a C++ component is the same as subscribing to an event in a .NET Framework class:
C#
Copy
JavaScript has an addEventListener method that enables multiple handlers to subscribe to a single event.
C++
C++
Copy
JavaScript
JScript
Copy
.NET
In C#, any number of event handlers can subscribe to the event by using the += operator as shown in the previous example.
Enums
A Windows Runtime enum in C++ is declared by using public class enum; it resembles a scoped enum in standard C++.
C++
C++
Copy
JavaScript
Enum values are passed between C++ and JavaScript as integers. You can optionally declare a JavaScript object that contains the same named values as the C++ enum and use it as follows.
JScript
Copy
.NET
Both C# and Visual Basic have language support for enums. These languages see a C++ public enum class just as they would see a .NET Framework enum.
Asynchronous methods
To consume asynchronous methods that are exposed by other Windows Runtime objects, use thetask Class (Concurrency Runtime) For more information, seeAsychronous
Programming in C++ andTask Parallelism (Concurrency Runtime).
To implement asynchronous methods in C++, use the
create_async function that's defined in ppltasks.h. For more information, seeCreating Asynchronous Operations in C++ for Windows Store Apps. For an example,
seeWalkthrough: Creating a basic Windows Runtime component in C++ and calling it from JavaScript. The .NET languages consume C++ asynchronous methods just
as they would any asynchronous method that's defined in the .NET Framework.
Exceptions
You can throw any exception type that's defined by the Windows Runtime. You cannot derive custom types from any Windows Runtime exception type. However, you can throwCOMException and provide a custom
HRESULT that can be accessed by the code that catches the exception. There's no way to specify a custom Message in aCOMException.
Debugging tips
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, select the JavaScript
project node in Solution Explorer and then choose
Properties, Debugging, Debugger Type.
Be sure to select appropriate capabilities in the package designer. For example, if you are attempting to open a file by using the Windows Runtime APIs, be sure to select theDocument Library Access check box in the
Capabilities pane of the package designer.
If your JavaScript code doesn't seem to be recognizing the public properties or methods in the component, make sure that in JavaScript you are using camel casing. For example, theLogCalc C++ method must be referenced as
logCalc in JavaScript.
If you remove a C++ Windows Runtime component project from a solution, you must also manually remove the project reference from the JavaScript project. Failure to do so prevents subsequent debug or build operations. If necessary, you can then add an assembly
reference to the DLL.
See Also
Developing Bing Maps Trip Optimizer, a Windows Store app in JavaScript and C++
To get the performance advantage of C++ in complex or computationally intensive operations.
To reuse code that's already written and tested.
When you build a solution that contains a JavaScript or .NET project, and a Windows Runtime component project, the JavaScript project files and the compiled DLL are merged into one package, which you can debug locally in the simulator or remotely on a tethered
device. You can also distribute just the component project as an Extension SDK. For more information, seeHow to: Create a Software Development Kit.
In general, when you code your C++ component, use the regular C++ library and built-in types, except at the abstract binary interface (ABI) boundary where you are passing data to and from code in another .winmd package. There, use Windows Runtime types and
the special syntax that Visual C++ supports for creating and manipulating those types. In addition, in your Visual C++ code, use types such asdelegate and
event to implement events that can be fired from your component and handled in JavaScript, Visual Basic, or C#. For more information about the new Visual C++ syntax, seeVisual
C++ Language Reference (C++/CX).
Casing and naming rules
JavaScript
JavaScript is case-sensitive. Therefore, you must follow these casing conventions:
When you reference C++ namespaces and classes, use the same casing that's used on the C++ side.
When you call methods, use camel casing even if the method name is capitalized on the C++ side. For example, a C++ methodGetDate() must be called from JavaScript as
getDate().
An activatable class name and namespace name can't contain UNICODE characters.
.NET
The .NET languages follow their normal casing rules.
Instantiating the object
Only Windows Runtime types can be passed across the ABI boundary. The compiler will raise an error if the component has a type likestd::wstring as a return type or parameter in a public method. The Visual C++ component extensions (C++/CX)
built-in types include the usual scalars such asint and
double, and also their typedef equivalentsint32,
float64, and so on.For more information, seeType System (C++/CX).
C++
C++
Copy
// ref class definition in C++ public ref class SampleRefClass sealed { // Class members... // #include <valarray> public: double LogCalc(double input) { // Use C++ standard library as usual. return std::log(input); } };
JavaScript
JScript
Copy
//Instantiation in JavaScript (requires "Add reference > Project reference") var nativeObject = new CppComponent.SampleRefClass();
.NET
C#
Copy
//Call a method and display result in a XAML TextBlock var num = nativeObject.LogCalc(21.5); ResultText.Text = num.ToString();
C++ built-in types, library types, and Windows Runtime types
An activatable class (also known as a ref class) is one that can be instantiated from another language such as JavaScript, C# or Visual Basic. To be consumable from another language, a component must contain at least one activatable class.
A Windows Runtime component can contain multiple public activatable classes as well as additional classes that are known only internally to the component. All public classes must reside in the same root namespace which has the same name as the component
metadata file. Apply the [WebHostHidden] attribute to C++ types that are not intended to be visible to JavaScript.
Client code creates an instance of the component by using the new (New in Visual Basic) keyword just as for any class.
An activatable class must be declared as public ref class sealed. Theref class keyword tells the compiler to create the class as a Windows Runtime compatible type, and thesealed
keyword specifies that the class cannot be inherited. The Windows Runtime does not currently support a generalized inheritance model; a limited inheritance model supports creation of custom XAML controls. For more information, see
Ref classes and structs (C++/CX).
For C++, all the numeric primitives are defined in the default namespace. The
Platform Namespace contains C++ classes that are specific to the Windows Runtime type system. These includePlatform::String
Class andPlatform::Object Class. The concrete collection types such asPlatform::Collections::Map
Class andPlatform::Collections::Vector Class are defined in thePlatform::Collections
Namespace. The public interfaces that these types implement are defined inWindows::Foundation::Collections Namespace (C++/CX). It is these interface
types that are consumed by JavaScript, C# and Visual Basic. For more information, see
Type System (C++/CX).
Method that returns a value of built-in type
C++C++
Copy
// #include <valarray> public: double LogCalc(double input) { // Use C++ standard library as usual. return std::log(input); }
JavaScript
JScript
Copy
//Call a method var nativeObject = new CppComponent.SampleRefClass; var num = nativeObject.logCalc(21.5); document.getElementById('P2').innerHTML = num;
.NET
Method that returns a custom value struct
A value struct is a plain old data object that can contain fields which are public by default. Avalue struct is passed by value.C++
C++
Copy
namespace CppComponent { // Custom struct public value struct PlayerData { Platform::String^ Name; int Number; double ScoringAverage; }; public ref class Player sealed { private: PlayerData m_player; public: property PlayerData PlayerStats { PlayerData get(){ return m_player; } void set(PlayerData data) {m_player = data;} } }; }
JavaScript
To pass user-defined value structs across the ABI, define a JavaScript object that has the same members as the value struct that's defined in C++. You can then pass that object as an argument to a C++ method so that the object is implicitly converted to
the C++ type.
JScript
Copy
// Get and set the value struct function GetAndSetPlayerData() { // Create an object to pass to C++ var myData = { name: "Bob Homer", number: 12, scoringAverage: .357 }; var nativeObject = new CppComponent.Player(); nativeObject.playerStats = myData; // Retrieve C++ value struct into new JavaScript object var myData2 = nativeObject.playerStats; document.getElementById('P3').innerHTML = myData.name + " , " + myData.number + " , " + myData.scoringAverage.toPrecision(3); }
Another approach is to define a class that implements IPropertySet (not shown).
C#
In the .NET languages, you just create a variable of the type that's defined in the C++ component.
C#
Copy
private void GetAndSetPlayerData() { // Create a ref class var player = new CppComponent.Player(); // Create a variable of a value struct // type that is defined in C++ CppComponent.PlayerData myPlayer; myPlayer.Name = "Babe Ruth"; myPlayer.Number = 12; myPlayer.ScoringAverage = .398; // Set the property player.PlayerStats = myPlayer; // Get the property and store it in a new variable CppComponent.PlayerData myPlayer2 = player.PlayerStats; ResultText.Text += myPlayer.Name + " , " + myPlayer.Number.ToString() + " , " + myPlayer.ScoringAverage.ToString(); }
Overloaded methods
A C++ public ref class can contain overloaded methods, but JavaScript has limited ability to differentiate overloaded methods. For example, it can tell the difference between these signatures:C++
Copy
public ref class NumberClass sealed { public: int GetNumber(int i); int GetNumber(int i, Platform::String^ str); double GetNumber(int i, MyData^ d); };
But it can’t tell the difference between these:
C++
Copy
int GetNumber(int i); double GetNumber(double d);
or these:
In ambiguous cases, you can ensure that JavaScript always calls a specific overload by applying theWindows::Foundation::Metadata::DefaultOverload attribute to the method signature in the header file.
This JavaScript always calls the attributed overload:
JScript
Copy
var nativeObject = new CppComponent.NumberClass(); var num = nativeObject.getNumber(9); document.getElementById('P4').innerHTML = num;
.NET
The .NET languages recognize overloads in a C++ ref class just as in any .NET Framework class.
DateTime
In the Windows Runtime, a Windows::Foundation::DateTime object is just a 64-bit signed integer that represents the number of 100-nanosecond intervals either before or after January 1, 1601. There are no methods on aWindows:Foundation::DateTime
object. Instead, each language projects the DateTime in the way that is native to that language: theDate object in JavaScript and the
System.DateTime andSystem.DateTimeOffset types in the .NET Framework.
C++
C++
Copy
public ref class MyDateClass sealed { public: property Windows::Foundation::DateTime TimeStamp; void SetTime(Windows::Foundation::DateTime dt) { auto cal = ref new Windows::Globalization::Calendar(); cal->SetDateTime(dt); TimeStamp = cal->GetDateTime(); // or TimeStamp = dt; } };
JavaScript
When you pass a DateTime value from C++ to JavaScript, JavaScript accepts it as aDate object and displays it by default as a long-form date string.
JScript
Copy
function SetAndGetDate() { var nativeObject = new CppComponent.MyDateClass(); var myDate = new Date(1956, 4, 21); nativeObject.setTime(myDate); var myDate2 = nativeObject.timeStamp; //prints long form date string document.getElementById('P5').innerHTML = myDate2; }
.NET
When a .NET language passes a System.DateTime to a C++ component, the method accepts it as aWindows::Foundation::DateTime. When the component passes a
Windows::Foundation::DateTime to a .NET Framework method, the Framework method accepts it as aDateTimeOffset.
C#
Copy
private void DateTimeExample() { // Pass a System.DateTime to a C++ method // that takes a Windows::Foundation::DateTime DateTime dt = DateTime.Now; var nativeObject = new CppComponent.MyDateClass(); nativeObject.SetTime(dt); // Retrieve a Windows::Foundation::DateTime as a // System.DateTimeOffset DateTimeOffset myDate = nativeObject.TimeStamp; // Print the long-form date string ResultText.Text += myDate.ToString(); }
Collections and arrays
Collections are always passed across the ABI boundary as handles to Windows Runtime types such asWindows::Foundation::Collections::IVector^ and
Windows::Foundation::Collections::IMap^. For example, if you return a handle to aPlatform::Collections::Map, it implicitly converts to a
Windows::Foundation::Collections::IMap^. The collection interfaces are defined in a namespace that's separate from the C++ classes that provide the concrete implementations. JavaScript and .NET languages consume the interfaces. For more information,
see Collections (C++/CX) andArray and WriteOnlyArray (C++/CX).
Passing IVector
C++C++
Copy
// Windows::Foundation::Collections::IVector across the ABI. //#include <algorithm> //#include <collection.h> Windows::Foundation::Collections::IVector<int>^ SortVector(Windows::Foundation::Collections::IVector<int>^ vec) { std::sort(begin(vec), end(vec)); return vec; }
JavaScript
JScript
Copy
var nativeObject = new CppComponent.CollectionExample(); // Call the method to sort an integer array var inVector = [14, 12, 45, 89, 23]; var outVector = nativeObject.sortVector(inVector); var result = "Sorted vector to array:"; for (var i = 0; i < outVector.length; i++) { outVector[i]; result += outVector[i].toString() + ","; } document.getElementById('P6').innerHTML = result;
.NET
The .NET languages see IVector<T> as IList<T>.
C#
Copy
private void SortListItems() { IList<int> myList = new List<int>(); myList.Add(5); myList.Add(9); myList.Add(17); myList.Add(2); var nativeObject = new CppComponent.CollectionExample(); IList<int> mySortedList = nativeObject.SortVector(myList); foreach (var item in mySortedList) { ResultText.Text += " " + item.ToString(); } }
Passing IMap
C++C++
Copy
// #include <map> //#include <collection.h> Windows::Foundation::Collections::IMap<int, Platform::String^> ^GetMap(void) { Windows::Foundation::Collections::IMap<int, Platform::String^> ^ret = ref new Platform::Collections::Map<int, Platform::String^>; ret->Insert(1, "One "); ret->Insert(2, "Two "); ret->Insert(3, "Three "); ret->Insert(4, "Four "); ret->Insert(5, "Five "); return ret; }
JavaScript
JScript
Copy
// Call the method to get the map var outputMap = nativeObject.getMap(); var mStr = "Map result:" + outputMap.lookup(1) + outputMap.lookup(2) + outputMap.lookup(3) + outputMap.lookup(4) + outputMap.lookup(5); document.getElementById('P7').innerHTML = mStr;
.NET
The .NET languages see IMap as IDictionary<K,V>.
C#
Copy
private void GetDictionary() { var nativeObject = new CppComponent.CollectionExample(); IDictionary<int, string> d = nativeObject.GetMap(); ResultText.Text += d[2].ToString(); }
Properties
A public ref class in Visual C++ component extensions exposes public data members as properties, by using theproperty keyword. The concept is identical to .NET Framework properties. A trivial property resembles a data
member because its functionality is implicit. A non-trivial property has explicit get and set accessors and a named private variable that's the "backing store" for the value. In this example, the private membervariable _propertyAValue is the
backing store for PropertyA. A property can fire an event when its value changes, and a client app can register to receive that event.
C++
C++
Copy
//Properties public delegate void PropertyChangedHandler(Platform::Object^ sender, int arg); public ref class PropertyExample sealed { public: PropertyExample(){} // Event that is fired when PropetyA changes event PropertyChangedHandler^ PropertyChangedEvent; // Property that has custom setter/getter property int PropertyA { int get() { return m_propertyAValue; } void set(int propertyAValue) { if (propertyAValue != m_propertyAValue) { m_propertyAValue = propertyAValue; // Fire event. (See event example below.) PropertyChangedEvent(this, propertyAValue); } } } // Trivial get/set property that has a compiler-generated backing store. property Platform::String^ PropertyB; private: // Backing store for propertyA. int m_propertyAValue; };
JavaScript
JScript
Copy
var nativeObject = new CppComponent.PropertyExample(); var propValue = nativeObject.propertyA; document.getElementById('P8').innerHTML = propValue; //Set the string property nativeObject.propertyB = "What is the meaning of the universe?"; document.getElementById('P9').innerHTML += nativeObject.propertyB;
.NET
The .NET languages access properties on a native C++ object just as they would on a .NET Framework object.
C#
Copy
private void GetAProperty() { // Get the value of the integer property // Instantiate the C++ object var obj = new CppComponent.PropertyExample(); // Get an integer property var propValue = obj.PropertyA; ResultText.Text += propValue.ToString(); // Set a string property obj.PropertyB = " What is the meaning of the universe?"; ResultText.Text += obj.PropertyB; }
Delegates and events
A delegate is a Windows Runtime type that represents a function object. You can use delegates in connection with events, callbacks, and asynchronous method calls to specify an action to be performed later. Like a function object, the delegate
provides type-safety by enabling the compiler to verify the return type and parameter types of the function. The declaration of a delegate resembles a function signature, the implementation resembles a class definition, and the invocation resembles a function
invocation.
Adding an event listener
You can use the event keyword to declare a public member of a specified delegate type. Client code subscribes to the event by using the standard mechanisms that are provided in the particular language.C++
C++
Copy
public: event SomeHandler^ someEvent;
This example uses the same C++ code as for the previous properties section.
JavaScript
JScript
Copy
function Button_Click() { var nativeObj = new CppComponent.PropertyExample(); // Define an event handler method var singlecasthandler = function (ev) { document.getElementById('P10').innerHTML = "The button was clicked and the value is " + ev; }; // Subscribe to the event nativeObj.onpropertychangedevent = singlecasthandler; // Set the value of the property and fire the event var propValue = 21; nativeObj.propertyA = 2 * propValue; }
.NET
In the .NET languages, subscribing to an event in a C++ component is the same as subscribing to an event in a .NET Framework class:
C#
Copy
//Subscribe to event and call method that causes it to be fired. private void TestMethod() { var objWithEvent = new CppComponent.PropertyExample(); objWithEvent.PropertyChangedEvent += objWithEvent_PropertyChangedEvent; objWithEvent.PropertyA = 42; } //Event handler method private void objWithEvent_PropertyChangedEvent(object __param0, int __param1) { ResultText.Text = "the event was fired and the result is " + __param1.ToString(); }
Adding multiple event listeners for one event
JavaScript has an addEventListener method that enables multiple handlers to subscribe to a single event.C++
C++
Copy
public delegate void SomeHandler(Platform::String^ str); public ref class LangSample sealed { public: event SomeHandler^ someEvent; property Platform::String^ PropertyA; // Method that fires an event void FireEvent(Platform::String^ str) { someEvent(Platform::String::Concat(str, PropertyA->ToString())); } //... };
JavaScript
JScript
Copy
// Add two event handlers var multicast1 = function (ev) { document.getElementById('P11').innerHTML = "Handler 1: " + ev.target; }; var multicast2 = function (ev) { document.getElementById('P12').innerHTML = "Handler 2: " + ev.target; }; var nativeObject = new CppComponent.LangSample(); //Subscribe to the same event nativeObject.addEventListener("someevent", multicast1); nativeObject.addEventListener("someevent", multicast2); nativeObject.propertyA = "42"; // This method should fire an event nativeObject.fireEvent("The answer is ");
.NET
In C#, any number of event handlers can subscribe to the event by using the += operator as shown in the previous example.
Enums
A Windows Runtime enum in C++ is declared by using public class enum; it resembles a scoped enum in standard C++.
C++
C++
Copy
public enum class Direction {North, South, East, West}; public ref class EnumExampleClass sealed { public: property Direction CurrentDirection { Direction get(){return m_direction; } } private: Direction m_direction; };
JavaScript
Enum values are passed between C++ and JavaScript as integers. You can optionally declare a JavaScript object that contains the same named values as the C++ enum and use it as follows.
JScript
Copy
var Direction = { 0: "North", 1: "South", 2: "East", 3: "West" }; //. . . var nativeObject = new CppComponent.EnumExampleClass(); var curDirection = nativeObject.currentDirection; document.getElementById('P13').innerHTML = Direction[curDirection];
.NET
Both C# and Visual Basic have language support for enums. These languages see a C++ public enum class just as they would see a .NET Framework enum.
Asynchronous methods
To consume asynchronous methods that are exposed by other Windows Runtime objects, use thetask Class (Concurrency Runtime) For more information, seeAsychronous
Programming in C++ andTask Parallelism (Concurrency Runtime).
To implement asynchronous methods in C++, use the
create_async function that's defined in ppltasks.h. For more information, seeCreating Asynchronous Operations in C++ for Windows Store Apps. For an example,
seeWalkthrough: Creating a basic Windows Runtime component in C++ and calling it from JavaScript. The .NET languages consume C++ asynchronous methods just
as they would any asynchronous method that's defined in the .NET Framework.
Exceptions
You can throw any exception type that's defined by the Windows Runtime. You cannot derive custom types from any Windows Runtime exception type. However, you can throwCOMException and provide a custom
HRESULT that can be accessed by the code that catches the exception. There's no way to specify a custom Message in aCOMException.
Debugging tips
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, select the JavaScript
project node in Solution Explorer and then choose
Properties, Debugging, Debugger Type.
Be sure to select appropriate capabilities in the package designer. For example, if you are attempting to open a file by using the Windows Runtime APIs, be sure to select theDocument Library Access check box in the
Capabilities pane of the package designer.
If your JavaScript code doesn't seem to be recognizing the public properties or methods in the component, make sure that in JavaScript you are using camel casing. For example, theLogCalc C++ method must be referenced as
logCalc in JavaScript.
If you remove a C++ Windows Runtime component project from a solution, you must also manually remove the project reference from the JavaScript project. Failure to do so prevents subsequent debug or build operations. If necessary, you can then add an assembly
reference to the DLL.
See Also
Concepts
Walkthrough: Creating a basic Windows Runtime component in C++ and calling it from JavaScriptOther Resources
Roadmap for Windows Store apps using C++Developing Bing Maps Trip Optimizer, a Windows Store app in JavaScript and C++
相关文章推荐
- WinRT开发系列之基础概念:WinRT不是……
- WinRT中读取基础数据类型
- javascript基础的动画教程,直观易懂
- 自动化(Automation)基础概念:COM组件(Component)与接口(Interface)
- Shell编程基础
- (一)linux基础及文件系统
- 公文管理基础
- VMware vSphere 5:最佳云基础架构平台
- 黑马程序员_基础进阶自学笔记
- SQL语言基础二
- Eclipse插件开发之基础篇(2) 第一个Eclipse插件
- PhoneGap入门经典——理解PhoneGap应用程序基础
- java 文件基础操作
- WinRT应用程序开发的那些事儿
- 黑马程序员-------.net基础知识二
- 读书笔记——Windows环境下32位汇编语言程序设计(3)一些基础知识
- C语言基础笔试面试题
- nodejs入门之基础HTTP请求
- 安卓系列基础教程之TextView控件
- Java编程算法基础----组合数学实践