none
C++/CLI 配列の型  RRS feed

  • 質問

  • お世話になります。

    C++/CLIでの多次元配列のアンマネージ型とマネージ型の相互運用について勉強中で、
    コンソールの引数をアンマネージ型にする方法を模索中で、下記のコードを作成したのですが、
    前記と直接関係のない質問ですが、※の方法をとるとコンパイルエラーとなってしまいます。
    明示的に型に落としてから使用することで対応できたのですが、なにがだめなのかが理由がわかりません。
    ご教授ください。

    int main(array<System::String ^> ^args)
    {

     const char** pp = new const char*[args->Length];

     marshal_context^ context = gcnew marshal_context();
     for(int i=0; i<args->Length; i++)
     {
      //pp[i] = context->marshal_as<const char*>( args[i] ); // コンパルエラー(※)
      String^ s = args[i];
      pp[i] = context->marshal_as<const char*>( s );
     }

     for(int i=0; i<args->Length;i++)
     {
      std::cout << pp[i] << std::endl;
     }
     delete context;

     return 0;
    }

    2010年11月18日 5:03

すべての返信

  • >※の方法をとる

    Compileも通りますし実行もできますよ。実行時に例外も発生しません。具体的にどのような状況でしょうか?

    2010年11月18日 10:57
  • >※の方法をとる
    Compileも通りますし実行もできますよ。実行時に例外も発生しません。具体的にどのような状況でしょうか?

    VS2010 で 「※」のある行のコメントを外すとコンパイルエラーになりました。
    参考までに。

    # 原因までは何ともいえません。
    # String^ const& の意味するところを説明できなさそうなので。orz


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年11月18日 14:20
    モデレータ
  • #include <msclr\marshal.h>

    を追加したらコンパイル通りました。

    #include "stdafx.h"
    #include <iostream>
    #include <msclr\marshal.h>
    
    using namespace System;
    using namespace msclr::interop;
    
    int main(array<System::String ^> ^args)
    {
    	const char** pp = new const char*[args->Length];
    
    	marshal_context^ context = gcnew marshal_context();
    	for(int i=0; i<args->Length; i++)
    	{
    		pp[i] = context->marshal_as<const char*>( args[i] );
    	}
    
    	for(int i=0; i<args->Length;i++)
    	{
    		std::cout << pp[i] << std::endl;
    	}
    	delete context;
    
    	int i = 0;
    	std::cin >> i;
    
    	return 0;
    }

    ひらぽん http://d.hatena.ne.jp/hilapon/
    2010年11月19日 6:06
  • #include <msclr\marshal.h>を追加したらコンパイル通りました。

    それがなかったら、marshal_contextが使えないんじゃないんですか?

    2010年11月19日 6:19
  • > それがなかったら、marshal_contextが使えないんじゃないんですか?

    確かに・・・思いっきり外しました。orz
    というわけで、

    > 前記と直接関係のない質問ですが、※の方法をとるとコンパイルエラーとなってしまいます。
    > 明示的に型に落としてから使用することで対応できたのですが、なにがだめなのかが理由がわかりません。

    こちらの環境(VS2010)では問題なくコンパイルできるため不明です(汗

    #同じ VS2010 でも Azulean さんはコンパイルが通らないといってるので何とも判りません。


    ひらぽん http://d.hatena.ne.jp/hilapon/
    2010年11月19日 6:58
  • 私が確認したCodeは以下の通りです。

    #include "stdafx.h"
    #include <msclr\marshal.h>
    #include <iostream>
    
    using namespace System;
    using namespace msclr::interop;
    
    int main(array<System::String ^> ^args)
    {
    	const char** pp = new const char*[args->Length];
    
    	marshal_context^ context = gcnew marshal_context();
    	for(int i=0; i<args->Length; i++)
    	{
    		pp[i] = context->marshal_as<const char*>( args[i] ); // コンパルエラー(※)
    		//String^ s = args[i];
    		//pp[i] = context->marshal_as<const char*>( s );
    	}
    
    	for(int i=0; i<args->Length;i++)
    	{
    		std::cout << pp[i] << std::endl;
    	}
    
    	delete context;
    
      return 0;
    }
    

    include <msclr\marshal.h>
    がないと、以下のErrorが発生します。

    error C2059: syntax error : 'const'
    error C2061: syntax error : identifier 'marshal_context'	
    error C2065: 'context' : undeclared identifier	
    error C2065: 'context' : undeclared identifier	
    error C2065: 'context' : undeclared identifier	
    error C2065: 'marshal_context' : undeclared identifier	
    error C2227: left of '->marshal_as' must point to class/struct/union/generic type
    error C2541: 'delete' : cannot delete objects that are not pointers	
    error C2653: 'msclr' : is not a class or namespace name	
    error C2871: 'interop' : a namespace with this name does not exist
    

    includeとusing namespaceを確認してみてください。

    ついでに動作確認もしていますので、これと同じ状況であれば、単純に必要なHeaderをincludeしていないだけだと思います。

    何れにせよ、詳しい状況の説明をお待ちしております。

    2010年11月19日 9:17
  • あら、通る方もおられるようなのでよくわからないなぁ。
    詳しいところは調べていませんが、私の環境(Win7-x86 + VS2008/2010)では以下のようなエラーを確認しています。
    (TAKAKUN さんのエラーとは異なる可能性があります。ご注意ください)

    error C2664: '_To_Type msclr::interop::marshal_context::marshal_as<const char*,System::String^>(const _From_Type &)' : 1 番目の引数を 'System::String ^' から 'System::String ^const &' に変換できません。(新しい機能 ; ヘルプを参照)
            with
            [
                _To_Type=const char *,
                _From_Type=System::String ^
            ]
            gc ヒープ (マネージ配列の要素) からのオブジェクトをネイティブ参照に変換できません

    CLR プロジェクトのコンソールプロジェクトを作成し、作成された main 関数のある cpp ファイルを、kozz さんが記載されているソースコードに完全に置換した場合に上記のエラーが出ていました。

    # 私の環境不備、手順ミスの可能性もありますが、未検証。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 編集済み AzuleanMVP, Moderator 2010年11月22日 10:58 名前を間違えていました。すみません。
    2010年11月19日 13:57
    モデレータ
  • marshal_contextには以下のtemplate Methodがあります。

    template<class _To_Type, class _From_Type>
    inline _To_Type marshal_as(const _From_Type& _from) 
    {
    	typedef context_node<_To_Type, _From_Type> _cn;
    	return internal_marshaler<_To_Type, _From_Type, _cn::_Needs_Context>::marshal_as(_from, _clean_up_list);
    }
    
    template<class _To_Type, class _From_Type>
    inline _To_Type marshal_as(_From_Type^ _from) 
    {
    	typedef context_node<_To_Type, _From_Type^> _cn;
    	return internal_marshaler<_To_Type, _From_Type^, _cn::_Needs_Context>::marshal_as(_from, _clean_up_list);
    }
    
    

    私の場合、下のMethodが参照されているようです。

    Azuleanさんの場合、上のMethodが参照されているようですね。

    そもそもref classに対して&は使えないはずですし、何が起きているのでしょうね。

     

     

    2010年11月20日 4:59
  • まったく別の環境に Win7-x86 + VS2010 を入れて試してみたところビルドが通りました。
    私の自宅の環境は何か悪さしてるかもしれません。orz
    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年11月20日 9:58
    モデレータ
  • 私の自宅の環境は何か悪さしてるかもしれません。orz

    私の環境に関してのフォローアップです。

    VS2010 初回起動時に、前のバージョンを引き継ぐような設定を入れていたせいか、プロジェクト新規作成時に「プラットフォーム ツールセット」が「v90」になっていました。
    「devenv /resetuserdata」で設定をリセットし、初回起動時の選択の前のバージョンを引き継ぐのチェックを消して初期化し直し、新規にプロジェクトを作成すると、ツールセットが「v100」になり、ビルドも通るようになりました。

    なお、以前に作成していたプロジェクトもプロジェクトのプロパティ、全般にある「プラットフォーム ツールセット」を「v100」にすればビルドが通りました。

    TAKAKUN さんの事例がどうかはわかりませんが、一つのトラブル事例と言うことで掲載しておきます。

    # 帰りの新幹線の中でこの可能性に気づいた。orz


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    • 編集済み AzuleanMVP, Moderator 2010年11月22日 10:58 名前間違えていました。すみません。
    2010年11月21日 14:54
    モデレータ
  • みなさまご返事ありがとうございます。

    私の環境を明示するのを忘れていましたが、VS2008(V90)です。
    またエラー内容も、Azuleanさんが提示された内容と同じです。

    Azuleanさんの内容からすると、VS2008では解決できない問題となるですかね。。。

    2010年11月22日 0:34
  • Azuleanさんの内容からすると、VS2008では解決できない問題となるですかね。。。
    VS2008 のヘッダーには "inline _To_Type marshal_as(_From_Type^ _from)" がありません。
    VS2010 で追加された経緯などは把握していないのですみません。。。

    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年11月22日 11:08
    モデレータ
  • 2008だと再現しますね。原因は追究してみないと何とも言えません。

    参考までに、以下のような問題もあるようです。 

    [marshal_context::marshal_as<const char*> generates compilation error when used with class member fields]

     https://connect.microsoft.com/VisualStudio/feedback/details/481881/marshal-context-marshal-as-const-char-generates-compilation-error-when-used-with-class-member-fields?wa=wsignin1.0

    2010年11月22日 11:08