第38講 データベースソフト(住所録)の制作=並列処理の練習☆☆
第2話 
Form2の起動コードとString^型・string型相互の型変換について
#pragma once
#include"Form2.h"
namespace 住所録 {
  using namespace System;
  using namespace System::ComponentModel;
  using namespace System::Collections;
  using namespace System::Windows::Forms;
  using namespace System::Data;
  using namespace System::Drawing;
  using namespace System::Threading;
           ・
           ・
           ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
        }
  private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
          Thread^ t=gcnew Thread(gcnew ThreadStart(f));
          t->Start();
        }
        static void f(){
          Application::Run(gcnew Form2());
        }

};

これでスレッドが起動します。
これから、内容を実装していきますが、
グローバル変数を使うために1つ注意が必要です。
並列処理ソリューションエクスプローラーを見ると
作った覚えのないForm2.cppが表示されています。
これは、実はForm2を作ると、自動的に制作されるものです。
赤囲いをダブルクリックすると、
Form2.cppが表示されます。
次のようにコーティングされいるはずです。
#include "StdAfx.h"
#include"Form2.h"

このうちの下の行を削ってください。
理由はわかりませんが、
これがあるとForm2で取得された値が反映されません。


さて、Form2で取得されるデータは、基本的に文字データです。
入門
文字データであると、String^型しか扱えません。
例えば、
char i[]=textBox1->Text;
とすると、

エラー 1 error C2440: '初期化中' : 'System::String ^' から 'char []' に変換できません。 c:\vc++2010\d3\a\a\Form1.h 122

とエラーします。
ところが、String^型はグローバル変数として宣言することも
namespaceの中の冒頭で宣言することもできません。
グローバル変数か名前空間の中で共有される変数でなければ、
Form2で取得された値を、Form1に反映させることは不可能です。

そこで、打つ手がないように見えるのですが、方法があります。
ヘッダファイルstdafx.h において
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または
// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
#pragma once
#include<msclr/marshal.h>        //後に使います。
#include<msclr/marshal_cppstd.h>   //後に使います。

#include<string>   //string型の変数を使うためにインクルードしておく必要があります。
using namespace msclr::interop;     //後に使います。
using namespace std; //string型の変数を使うために必要です。
static string u[100];

と宣言すれば、string型の変数はグローバルに宣言できます。
もちろん、string型はtextBox1->Textなどと直接のデータのやりとりはできません。
しかし、String^型をstring型に変更したり、string型をString^型したりする方法があります。
それを変更するには
#include<msclr/marshal.h> 
#include<msclr/marshal_cppstd.h> 
using namespace msclr::interop
が必要ななのです。
String^型をstring型に変更するために必要なインクルードファイルが#include<msclr/marshal_cppstd.h> です。
その逆、string型をString^型に変更するとき必要なインクルードファイルが#include<msclr/marshal.h>なのです。

具体例をだしてから、意味を説明します。

String^ w;
w=comboBox1->Text;
marshal_context^ c=gcnew marshal_context();
string s=c->marshal_as<string>(w);
delete c;

このコードは、
comboBox1->TextにあるString^型のデータをstring型に変身させて、
string型の変数に収納するものです。
私が参考にした入門書はこのコード次のように書いて初心者迷宮に誘い込んでいます。

String^ Sample;
Sample=comboBox1->Text;
marshal_context^ context=gcnew marshal_context();
string s=context->marshal_as<string>(w);
delete context;

このように書いたのでは
marshal_context^ context=gcnew marshal_context();
の2つのcontextのく別がつかなくなります。
また、Sample自体にも意味があると思ってしまいます。

さて、コードを元に戻しましょう。
String^ w;
w=comboBox1->Text;
marshal_context^ c=gcnew marshal_context();
string s=c->marshal_as<string>(w);
delete c;
最初の2行は、String^型の変数wを用意して、
そこにcomboBox1->Textのデータを収納するということです。
次のmarshal_context^ c=gcnew marshal_context();
に?を浮かべている読者がいると思います。これは、
marshal_context^ 変数=gcnew marshal_context();
ということです。cのところは変数ですから、
何でもよいわけです。わざわざcontextなどとする必要はさらさらありません。
私は、このサイトの方針=変数名は基本は1文字にするに従って、cにしただけです。
すると、marshal_context^は変数の型を表していることがわかります。
左辺marshal_context^ cは、marshal_context^型の変数cを宣言するという意味になります。
右辺のgcnew marshal_context()は、marshal_context^型として新た作り出すです。
つまり、marshal_context^ c=gcnew marshal_context();
はmarshal_context^型の変数cを新たに定義するです。
次の行
string s=c->marshal_as<string>(w);
の左辺はstring型の変数を用意する(宣言する)です。
右辺のmarshal_as<string>(w);はString^型のwをstringに変更せよ、です。
すると、c->やmarshal_context^ c=gcnew marshal_context();に何の意味があるのと疑問に思うでしょうが、
VC++の仕様がそのようになっているので仕方がありません。
お呪いとして受け取っていただくしかありません。

marshal_context^ c=gcnew marshal_context();
string s=c->marshal_as<string>(w);
は、
string s=marshal_as<string>(w);
で済むように、VC++の制作者に変更をお願いしたいものですね。
delete c;
はgcnewで作る変数は、関数が消滅しても消滅しないので自分で削除しなければなりません。


逆の変更、すなわちstring型をString^型へ変更に話題を変えましょう。
逆は非常にすっきりしています。
w=marshal_as<String^>(s);
右辺のmarshal_as<String^>(s)でstring型sがString^型に変身します。
では、皆さん
入門のデータが
並列処理
一覧表に反映されようにコーティングしてください。
今回は、一覧表の1行目だけに反映されればよいことにします。
尚、このソフトではForm2のマルチスレッドを押してから、Form1の並列プログラミングを押すとデータ反映されるようになっています。

第1話へ 第3話へ

戻る

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)