[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」を選択して作ります。

#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 );
    };
}

 

// 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 ;
}

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

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

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;
}

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

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

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

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;
}

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

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

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


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;
        }
    }
}

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

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

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

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;
}

普通にコーディングができてしまいます。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 になりますね。
      後ほど、記事を修正せねば。

コメントは停止中です。