次の方法で共有


Meshing in C++ (CLI)

I recently was asked about accessing the Live Framework from C++. Taking this from the standpoint of “Hey, I have a regular old C++ application. How can I start putting my stuff into Live Services using Live fx?” there are a couple of options.

  • REST/XML
  • C++ CLI Interop

These are reasonable alternatives depending on your particular team and your business needs. And yes, there are a few other unreasonable options such as rewriting your whole app in managed code, using .NET/COM interop to talk to the .NET toolkit, or writing your own JSON parser while heavily using the __asm keyword just for fun, but I’ll just forget you mentioned that and move along.

REST/XML

If you have an application which is already doing XML manipulation, then you may already have the skills and libraries in place to just start using Live fx directly. This would be just the same as if you were using java, python, php or whatever language currently doesn’t have a toolkit available. You just grab an XML library you are comfortable with and starting PUTing and GETing your way into your user’s Mesh.

C++ CLI Interop

This is where I think I would end up – mainly because I’m an old C++ hack who lives in a C# world now. With C++ CLI available, you can easily take just a single file or your whole project and build it with the capability to interact natively with .NET assemblies. Since the Live Framework SDK comes with a .NET toolkit, your application can call into the managed Live fx classes directly from C++.

In C++ you could list all the meshObjects like this

 LiveOperatingEnvironment^ loe = gcnew LiveOperatingEnvironment(); 
loe->ConnectLocal(); 
Mesh^ mesh = loe->Mesh; 
IQueryable<MeshObject^>^ meshObjects = mesh->CreateQuery<MeshObject^>(); 
for each (MeshObject ^ mo in meshObjects) 
{ 
  Console::WriteLine(mo->Resource->Title); 
} 

There is fairly straightforward and not too much different than C#, right? Well now comes the fun part – LINQ queries.

LINQ queries are very useful in the Live fx toolkits, because the toolkit can examine the queries and potentially send it over the wire to run on the server instead of running locally. The problem is that C++ doesn’t natively support LINQ. It can of course call the underlying classes and interfaces that actually run LINQ under the covers but it becomes pretty ugly when trying to do it directly.

Lets add a “simple” LINQ query to just find all the Mesh Objects that are titled “Documents”.  For those Lambda expression guys out there this is ‘mo => mo.Resource.Title == “Documents”’

 LiveOperatingEnvironment^ loe = gcnew LiveOperatingEnvironment(); 
loe->ConnectLocal(); 
Mesh^ mesh = loe->Mesh; 
IQueryable<MeshObject^>^ baseQuery = mesh->CreateQuery<MeshObject ^>();

// Define the left side of the lambda expression
ParameterExpression^ meshObj = 
    Expression::Parameter(baseQuery->ElementType, "meshObj");

// Define the right side of the lambda expression
// Need to use the PropertyInfo because of ambiguous 
// reflection of derived types
System::Reflection::PropertyInfo^ propInfo = 
    baseQuery->ElementType->GetProperty(
        "Resource", 
        Microsoft::LiveFX::ResourceModel::MeshObjectResource::typeid
    );
MemberExpression^ resourceProp = 
    Expression::Property(meshObj, propInfo);

// retrieve Title property of Resource property
MemberExpression^ titleProp = 
    Expression::Property(resourceProp, "Title");

// do the compare
Expression^ leftSide = titleProp;
Expression^ rightSide = Expression::Constant("Documents");
Expression^ finalExpression = Expression::Equal(leftSide, rightSide);
Expression<Func<MeshObject^,bool>^>^ whereExpression = 
    Expression::Lambda<Func<MeshObject^,bool>^>(finalExpression, meshObj);

IQueryable<MeshObject^>^ whereQuery = 
    Queryable::Where<MeshObject^>(baseQuery, whereExpression);

for each (MeshObject ^ mo in whereQuery)
{
    Console::WriteLine(mo->Resource->Title);
}

That little query just added a whole lot of complexity because we have to build the expression tree by hand. Again, C++ doesn’t support LINQ syntax – but the queries are extremely useful and you are probably going to end up using them quite a bit. So how do we simplify this? We interop to our own C# assembly instead. In C# this same code collapses to

 LiveOperatingEnvironment^ loe = gcnew LiveOperatingEnvironment(); 
loe->ConnectLocal(); 
Mesh^ mesh = loe->Mesh; 

var meshObjects = from mo in mesh.CreateQuery<MeshObject>()
    where mo.Resource.Title == "Documents"
    select mo;

foreach (MeshObject mo in meshObjects)
{
    Console.WriteLine(mo.Resource.Title);
}

Using C++ CLI, you can continue to work your main application logic in C++ if you want, and then just call into a separate DLL which talks to the Mesh in C# (or VB) to greatly simplify your development effort.

The point is, C++ is not left out in the cold; but for any LINQish query filtering/ordering you do, I would do it in a separate .NET assembly to handle it in a language that handles the LINQ syntax naturally. Unless of course you enjoy building your own expression trees.

Comments

  • Anonymous
    December 15, 2008
    If Microsoft comes up with a native LiveFX SDK at some point, it would be cool if it supported Google's Native Client.  This way you could write a native Mesh-Enabled Web App that is deployed and managed by LiveFX/Mesh just like the Silverlight and JavaScript MEWAs, with full SDK support.