[win8] c++/cx から c# のライブラリは使えない…と思ったが使える

metro アプリケーションの作り方は、いくつかパターンが考えられて、

  • VB/C# 単体で作る。
  • C++/CX 単体で作る。
  • VB/C# でライブラリを作って、VB/C# で使う。
  • C++/CX でライブラリを作って、C++/CX で使う。

このように同じ言語で揃えるパターンの他にも、

  • C++/CX でライブラリを作って、VB/C# で利用する。
  • VB/C# でライブラリを作って、C++/CX で利用する。

というのがあります。さきの同じ言語の場合はスムースにいくのですが、他言語と mix する場合はどうなるかというと…実は、「VB/C# でライブラリを作って、C++/CX で利用する」という方法は取れません。あまり明記はされていないのですが、C#/VB の場合は、.NET Framework を使っていて、C++/CX では WinRT のみ使っている且つ .NET Framework が使えない、ということを考えると、c++/cx から c# は使えんだろう、という想像ができます。

という訳で、これを実験して確認しておきます。

■c++/cx で作ったライブラリを、c++/cx で使う

まずは、普通に使えるであろう、c++/cx だけの組み合わせを試してみます。

c++/cx のライブラリのほうは、こんな感じ。

「WinRT コンポーネントDLL」を選択して作ります。

[code lang=”csharp”]
#pragma once

namespace CppCxClassLib
{
public ref class Calc sealed
{
public:
Calc();
int Add( int x, int y );
Platform::String^ Add( Platform::String^ x, Platform::String^ y );
};
}
[/code]

 

[code lang=”csharp”]
// WinRTComponent.cpp
#include "pch.h"
#include "WinRTComponent.h"

using namespace CppCxClassLib;
using namespace Platform;

Calc::Calc()
{
}
int Calc::Add( int x, int y )
{
return x+y;
}

Platform::String^ Calc::Add( Platform::String^ x, Platform::String^ y )
{
return x + y ;
}
[/code]

公開するクラスは「sealed」を付けておきます。

これを利用する c++/cx の画面のほうは、普通の metro アプリケーションで作ります。
参照設定で「CppCxClassLib」のライブラリを参照しておきます。

[code lang=”csharp”]
void CppCxUseCSharpLib::BlankPage::Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
CppCxClassLib::Calc^ calc = ref new CppCxClassLib::Calc();
int num = calc->Add( 10 , 20 );
textBox1->Text = num.ToString();

}

void CppCxUseCSharpLib::BlankPage::Button_Click_2(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
CppCxClassLib::Calc^ calc = ref new CppCxClassLib::Calc();
String^ s = calc->Add( L"masuda", L"tomoaki" );
textBox1->Text = s;
}
[/code]

これで普通の動くことを確認します。まあ、最初の動作確認ですね。

■c++/cx で作ったライブラリを、C# で使う

今度は、CppCxClassLib ライブラリを C# で利用します。

[code lang=”csharp”]
private void Button_Click_1(object sender, RoutedEventArgs e)
{
var calc = new CppCxClassLib.Calc();
int num = calc.Add(10, 20);
textBox1.Text = num.ToString();
}

private void Button_Click_2(object sender, RoutedEventArgs e)
{
var calc = new CppCxClassLib.Calc();
string s = calc.Add("masuda", "tomoaki");
textBox1.Text = s;
}
[/code]

書き方は、c++/cx と同じに使えます。CppCxClassLib ライブラリを参照設定すれば普通のライブラリと同様に使えます。

■C# で作ったライブラリを、C++/CX で使う?

さて、本題の C++/CX -> C# という向きはできるのでしょうか?という確認です。
まずは C# のライブラリを作成しておきます。

[code lang=”csharp”]

namespace CSharpClassLib
{
public sealed class Calc
{
/// <summary>
/// int 型を返す
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int Add(int x, int y)
{
return x + y;
}
/// <summary>
/// System.String 型を返す
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public string Add(string x, string y)
{
return x + y;
}
}
}
[/code]

中身は、C++/CX と同じものですね。

このライブラリを metro c++/cx から参照せっていすると…実は参照設定ができます。

参照設定をしただけでは別にエラーはでません。
では、コーディングを C# のライブラリを使うように書き直してみると…

[code lang=”csharp”]
void CppCxUseCSharpLib::BlankPage::Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
CSharpClassLib::Calc^ calc = ref new CSharpClassLib::Calc();
int num = calc->Add( 10 , 20 );
textBox1->Text = num.ToString();

}

void CppCxUseCSharpLib::BlankPage::Button_Click_2(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
CSharpClassLib::Calc^ calc = ref new CSharpClassLib::Calc();
String^ s = calc->Add( L"masuda", L"tomoaki" );
textBox1->Text = s;
}
[/code]

普通にコーディングができてしまいます。c++/cx のライブラリと同様にインテリセンスも効くので、コーディングは楽チンです。
なので、ひょっとするとこのまま c++/cx -> c# の向きは ok なのか、と思いきや実際コンパイルしてみるとエラーになります。

インテリセンスのエラーはないんですけどね。

という訳で、めでたく c/c++ -> c# への向きは「できません」ということです。

■まとめ

ライブラリの使い方としては、以下の通り。

  • OK: c# -> c#
  • OK: c++/cx -> c++/cx
  • OK: c# -> c++/cx
  • NG: c++/cx -> c#

ってことでチェック完了…と思いきや、実は C++/CX -> C# が使えます。

2012/05/24 追記

C# のライブラリの出力先を「WinMDファイル」にしておくと、C++/CX でも使えるようになりますね。これは便利。

なので、この話は別途書きます。

カテゴリー: C#, C++/CX, windows 8 パーマリンク

[win8] c++/cx から c# のライブラリは使えない…と思ったが使える への2件のフィードバック

  1. Egtra のコメント:

    C#のライブラリのプロジェクトのプロパティで「出力の種類」を「WinMDファイル」にすると、C++/CXから使用できるようになりますよ。私も、最初このことに気付かずc/c++ -> c#はできないと思っていました。

    • masuda のコメント:

      おお、確かにできます、できます。ありがとうございます。
      「WinMDファイル」にすると、C++/CX -> C# が ok になりますね。
      後ほど、記事を修正せねば。

コメントは停止中です。