C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: C#のoutをC++に(call by reference)


(過去ログ 97 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■57880 / inTopicNo.1)  C#のoutをC++に(call by reference)
  
□投稿者/ ken (13回)-(2011/03/19(Sat) 23:58:21)

分類:[C++/CLI] 

http://dobon.net/vb/dotnet/string/encryptstring.html
のC#サンプルプログラムををVisual C++ 2010に移植して勉強しています。もとのC#で

public static string EncryptString(string sourceString, string password)
{
(中略)
GenerateKeyFromPassword(password, rijndael.KeySize, out key, rijndael.BlockSize, out iv);
rijndael.Key = key;
rijndael.IV = iv;
(中略)
}

private static void GenerateKeyFromPassword(string password,
int keySize, out byte[] key, int blockSize, out byte[] iv)
{

(中略)
key = deriveBytes.GetBytes(keySize / 8);
iv = deriveBytes.GetBytes(blockSize / 8);
}

となっていていて、keyとivはoutを使って、call by referenceされている?ようです。
一方、これをC++にしようとしているのですが、

static String^ EncryptString(String^ sourceString, String^ password){
(中略)
  array<unsigned char>^ key;
array<unsigned char>^ iv;
  GenerateKeyFromPassword(password, rijndael->KeySize, key, rijndael->BlockSize, iv);
  rijndael->Key = key;
rijndael->IV = iv;
(中略)
}

static void GenerateKeyFromPassword(String^ password,int keySize, array<unsigned char> key, int blockSize, array<unsigned char>^ iv){

(中略)
key = deriveBytes->GetBytes(keySize / 8);
iv = deriveBytes->GetBytes(blockSize / 8);
}

としても、ビルト時にエラーは出ませんが、key、iv共に、参照渡しが出来ていません。非常に恥ずかしい質問ですが、どうすればよいのでしょうか?
あと、key、ivが、C#ではByte型、C++ではarray<unsigned char>になるようです。
引用返信 編集キー/
■57881 / inTopicNo.2)  Re[1]: C#のoutをC++に(call by reference)
□投稿者/ Azulean (710回)-(2011/03/20(Sun) 00:16:12)
たとえば、「c++/cli out」で検索して得られる情報で解決したりしませんか?
http://www.google.co.jp/search?hl=ja&source=hp&biw=1138&bih=761&q=c%2B%2B%2Fcli+out&btnG=Google+%E6%A4%9C%E7%B4%A2&aq=f&aqi=g1&aql=&oq=

解決しないのであれば、何がわかって、何がわからないのかを明確にした上で再質問してください。
(キーワードを選んで検索すると、結構解決することがあるので、聞く前に検索するというのはやっておいて損はないです)
引用返信 編集キー/
■57882 / inTopicNo.3)  Re[2]: C#のoutをC++に(call by reference)
□投稿者/ ken (14回)-(2011/03/20(Sun) 08:06:26)
どうもありがとうございます。C++は20年ほど前にかじったことがある程度で、戸惑っています。

 まず、C#のoutとrefについて調べましたが、C#では必ず変数を初期化せねばならないため、変数を宣言だけしておいて送った先で値を代入する場合は、outで初期化が省略できるのですね。

 次に、今回の私の件では元のC#ではbyte[]と宣言しているところを見ると配列で、C++ではByte型がないので、array<unsigned char>^を使うようです。ここまでは分かったのですが、配列を参照渡ししている例が見あたらず苦戦しています。
昔のCなら

int a[100]
func(a);

func(int a[]){
...
}

でいけたんですが…。 
引用返信 編集キー/
■57883 / inTopicNo.4)  Re[3]: C#のoutをC++に(call by reference)
□投稿者/ Azulean (711回)-(2011/03/20(Sun) 08:14:54)
2011/03/20(Sun) 08:17:25 編集(投稿者)

No57882 (ken さん) に返信
>  次に、今回の私の件では元のC#ではbyte[]と宣言しているところを見ると配列で、C++ではByte型がないので、array<unsigned char>^を使うようです。

System::Byte というようにすれば、System::Int32 とか使えますよ。
(もしくは、using namespace System; と書いておく)
http://msdn.microsoft.com/ja-jp/library/system.byte.aspx


> ここまでは分かったのですが、配列を参照渡ししている例が見あたらず苦戦しています。

ほかの参照型(クラス)と同じです。
System::String^ で見つかる事例と同じようにある 1 文字を付加すれば良いのです。

この手の場合、全く同じ事例が見つからないから諦めるのではなく、類似ケースを見つけてどのようなルールなのか想像してみてください。
(もし、このヒントでもわからない場合、言ってください。検索方法、ページをたどる過程を含めて紹介します)

> 昔のCなら
>
> int a[100]
> func(a);
>
> func(int a[]){
> ...
> }
>
> でいけたんですが…。

それではだめですよ。
C++/CLI でやっていることは func の中で a = (int*)malloc(sizeof(int) * 100); というような意味なのですから。
これだと、呼び出し元の a には何も効果がないどころか、メモリリークしていますよね。

# memcpy に相当するようなコードを書いていれば別ですが、C++/CLI のコードはそうなっていません。
引用返信 編集キー/
■57884 / inTopicNo.5)  Re[4]: C#のoutをC++に(call by reference)
□投稿者/ ken (15回)-(2011/03/20(Sun) 08:27:59)
2011/03/20(Sun) 09:37:53 編集(投稿者)

ありがとうございます。

以下のように書くとうまく行っているようなのですが、これで問題ないもんでしょうか。
ここを参考に書きました。

http://bear09.blog118.fc2.com/blog-entry-23.html

変数keyだけについて書きます。

−−−参照呼び出し側−−−
static String^ EncryptString( ){
<中略>
array<unsigned char>^ key;
GenerateKeyFromPassword(key);
<中略>
}

−−−参照受け側−−−
static void GenerateKeyFromPassword( [Runtime::InteropServices::Out] array<unsigned char>^% key){
key=なにかの値;
}

もう一点、
ICryptoTransform^ decryptor = rijndael->CreateDecryptor();
で宣言したdecryptorはDisposeに相当する処置は不要でよいでしょうか?VB、VC#にはDisposeメソッドがありますが、VCにはなく、gcnewで宣言したものでなければ、スコープから外れれば自動的にデストラクタが呼ばれるのかと思うのですが。
引用返信 編集キー/
■57888 / inTopicNo.6)  Re[5]: C#のoutをC++に(call by reference)
□投稿者/ Azulean (712回)-(2011/03/20(Sun) 18:50:12)
No57884 (ken さん) に返信
> static void GenerateKeyFromPassword( [Runtime::InteropServices::Out] array<unsigned char>^% key){

はい。上記で C# で言うところの out になります。
(C# でいう ref/out はこの % に相当し、out として見せるためには Out 属性をつけなければならない)

> もう一点、
> ICryptoTransform^ decryptor = rijndael->CreateDecryptor();
> で宣言したdecryptorはDisposeに相当する処置は不要でよいでしょうか?

ICryptoTransform インターフェースは IDisposable インターフェースを継承していますので、Dispose するべきだとみられます。


> VB、VC#にはDisposeメソッドがありますが、VCにはなく、gcnewで宣言したものでなければ、
> スコープから外れれば自動的にデストラクタが呼ばれるのかと思うのですが。

gcnew で作成したものは delete してください。
delete の呼び出しによって内部的に Dispose メソッドが呼び出されます。

^ は見た目上、ポインタに近い動きをします。
そういったものに対して、delete を呼ばなかった場合は、ファイナライザが呼び出される前でリソースが解放されないなどの問題を引き起こすことがあります。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -