C++/CLI part3at TECH
C++/CLI part3 - 暇つぶし2ch774:デフォルトの名無しさん
09/09/17 02:41:02
public value class NameInfo
{
   public: property Int32 ID;
};

public ref class NameHolder
{
   NameInfo _Name;
public:
  NameInfo get(){return _Name;}
// void set(NameInfo^ Name ){_Name = *Name;}
// void set(NameInfo& Name ){_Name = Name;}
  void set(NameInfo Name ){_Name = Name;}
};

int main(array<System::String ^> ^args)
{
  NameInfo Name;
  Name.ID = 10;
  NameHolder Holder;
  Holder.set(Name);
  NameInfo Buf1 = Holder.get();
  Console::WriteLine(Buf1.ID);
  Name.ID = 20;
  NameInfo Buf2 = Holder.get();
  Console::WriteLine(Buf2.ID);
  return 0;
}
どれも結果は 10、 10と表示され、値は登録後の値は変わりませんでした。
根本的に、なんか勘違いしてますかね?

775:デフォルトの名無しさん
09/09/17 02:49:44
メンバがいつの間にかハンドルじゃなくなったな

776:デフォルトの名無しさん
09/09/17 03:05:00
NameInfo^ _Name; これに変更。
NameHolder() { _Name = gcnew NameInfo(); } これ追加

してやって見ました。結果は同じでした。C++からハンドルが一つ増えただけで、こんなにも苦労するとは・・・・

777:デフォルトの名無しさん
09/09/17 03:10:40
もとのC++の記述と同じようにかきゃいいと思うけどな
value classならほぼ変わらんし
移植って時点で思想とか意味ないだろうし

778:デフォルトの名無しさん
09/09/17 03:19:20
元のコードにあわせてハンドルじゃなくしたのかと思ったけど、あっさりハンドルに戻すとか
ほんとに移植しようとしてるのかが疑問

779:デフォルトの名無しさん
09/09/17 03:54:00
>>770
ちなみに、ネイティブなC++だったら、そのsetの引数の型は、NameInfoかconst NameInfo&にするとこだよね。

自分だったら、NameInfoにするかなあ。コピーのコストが心配っていうならそもそも値型にしないし。
読み取りだけの引数にconst付けないのは嫌だ。

値型の場合、T& → T%、T* → interior_ptr<T>へと機械的に変換すればいい。
その上で、他言語で使えないのでconstは削除し、値型のハンドルも使わないのが自分の方針。

ちなみに、(1)の値型のハンドルで、>>774のようにボックス化されていない(ハンドルでないもの)を実引数にする場合、
ボックス化(ようは新しくメモリ確保してそこへ実引数をコピー)が行われるので(3)より遅いよ。

780:デフォルトの名無しさん
09/09/17 04:03:11
>>779
横からごめん
> 他言語で使えないのでconstは削除
というのはどういうこと?

781:デフォルトの名無しさん
09/09/17 04:20:29
>>780
C#などからそのメソッドを呼ぶ場合、あたかもconstはなかったかのように無視される。
そのため、自分はC++/CLIは他言語から呼び出すことを前提に使っているので、
C++/CLIの段階でpublicな型のpublicなメソッドの引数・戻り値にはconstを付けようと思わないというだけのこと。

つまり、これは自分1人の考えなんで、気にせずconst使うという人も中にはいると思う。

782:デフォルトの名無しさん
09/09/17 04:29:23
>>781
なるほど。勉強になりました。

783:774です。
09/09/17 04:39:15

いろいろとありがとうございます。
先輩にきいて、値を保持したいのであれば、このクラスを移植すれば良いとともらったソースを移植中です。
中身を見ると、シングルトン形式で値を保持しているようです。
C++であれば const NameInfo& Name なので、const NameInfo% Name にしたらコンパイラ君に怒られて
パニックになってしまいました。 
C++の時は、メンバー関数の後ろをはじめ、constをつけるように、強く教育を受けたので、CLIでもかんばって
つけようとするとことごとく怒られて・・・・。
NameInfo という値で渡すのがよさそうなので、これでいって見ようかと・・・。
教えていただいた 機械方式 NameInfo% にしたいですが、先輩に % は関数内で値を変えるとき意外は使うなといわれて・・・。
くそー 何でconst NameInfo%  て読み取り専用にできないだよ!!!!

784:デフォルトの名無しさん
09/09/17 07:46:38
constが付いていたら、自動生成した読み取り専用ラッパーに包んで返す。
……とかどうなんだろう。やっぱ駄目かなあ。

785:デフォルトの名無しさん
09/09/17 08:47:15
プロパティでgetterのみにすればいいんじゃないか?

786:デフォルトの名無しさん
09/09/17 10:14:48
値型^って普通使わないよ
一番効率悪いし他の言語では全く使えない

787:デフォルトの名無しさん
09/09/24 23:24:35
String型だけなんで^なしで宣言出来ないんだろう…
あとshortの列挙型に-32768が使えないのもわからん
C#なら通るのに

788:デフォルトの名無しさん
09/09/24 23:27:32
String型がcharの配列なので。
shortの-32768(全ビットon)は未定義値の代わりなので。

789:デフォルトの名無しさん
09/09/24 23:38:51
即レスありがとう
Stringの内部構造までは見たんだけど、つまりC++/CLIでは配列はスタックに作れないってことなのかな

790:デフォルトの名無しさん
09/09/25 04:34:30
動的にサイズを変えられるんだからヒープまたはマネージドヒープと考えるのが妥当なんじゃないの

791:デフォルトの名無しさん
09/09/25 07:45:38
^なしに記述しているのだって、別にスタックに配置している訳じゃないし

792:デフォルトの名無しさん
09/09/30 15:44:34
String型だけなんで^なしで宣言出来ないんだろう…

ref class だから

793:デフォルトの名無しさん
09/10/01 00:51:52
C++のRAIIパターンでDispose持ちの参照型を扱おうって意図だから
参照型でもこれはOKなんよ。
実際はDisposeのシグネチャを持ってる必要もないんだが。

ただ何故かStringとarrayは宣言できんのね。

794:デフォルトの名無しさん
09/10/06 00:13:56
deleteしたオブジェクトのファイナライザって呼ばれないの?
C++/CLIのデストラクタ=C#のDisposeだと思ってたんだけど

795:デフォルトの名無しさん
09/10/06 00:31:17
C#でもDisposeしたときはGC.SuppressFinalizeでファイナライザの呼び出しを抑制するが?

796:デフォルトの名無しさん
09/10/06 11:24:38
ファイナライザの呼び出しが有効になってるとGCのパフォーマンスに悪影響を与える。
明示的にDisposeが行われた後はファイナライザ呼び出しは不要なはずなので
ファイナライザを呼び出さないようにGCに指示するようになってる。
アンマネージリソースを直接持ってない限りはファイナライザ(!の方)は定義しない方がよい。

797:デフォルトの名無しさん
09/10/06 13:17:58
~ClassA()や!ClassA()はDispose()やFinalizerそのものではない。
正確にこのコードになるわけじゃないのだけれどイメージとして捉えて欲しい。
 ~ClassA() { }
 !ClassA() { }
上2つを使っていると、ここからはコンパイラが生成する。
 void Dispose(bool disposing) {
   if (disposing) ~ClassA(); else !ClassA();
 }
 void Dispose() {
   Dispose(true); GC.SuppressFinalize(this);
 }
 void Finalize() {
   Dispose(false);
 }



798:デフォルトの名無しさん
09/10/09 17:38:36
C/C++室より、案内されてこちらのスレに来ました。


void test(int x[]){cout << sizeof x << endl;return;}

int main(array<System::String ^> ^args)
{
  int x[] = {1,2,3,4,5};
  test(x);
  cout << sizeof x << endl;
}

■出力結果
4
20

なんで両方とも20にならないんでしょうか?

799:デフォルトの名無しさん
09/10/09 17:58:20
CLI一切関係ないな
仮引数が配列表記でも実際はポインタとして渡される

800:デフォルトの名無しさん
09/10/09 18:15:42
>>799
>CLI一切関係ないな
失礼しました。
void test(int x[]) が void test(int* x)として解釈されるという事ですね。
誘導元のほうでも親切な方が教えてくれました。

ありがとうございます。

801:デフォルトの名無しさん
09/10/10 02:32:29
ハンドル使ってるから脊髄反射したんだろう

802:デフォルトの名無しさん
09/10/10 16:37:37
>>801
つーか内部的にMSIL使ってる言語は気持ち悪いんだよ
全部こっちに回すから頼んだ

803:デフォルトの名無しさん
09/10/10 23:57:23
出力結果から想像できるだろうに。
近頃の子は自分で考えるってこと、しないのかねぇ。

804:デフォルトの名無しさん
09/10/11 09:13:05
void func(int *a);
とかアドレスを引数にする昔の関数に
int b;
func(&b);
などとすると、
cli::interior_ptr<Type>' から 'int *' に変換できません。
とかいうエラーが出てしまいます。
どうしたらいいでしょうか?

805:デフォルトの名無しさん
09/10/11 10:42:48
reinterpret_cast<Int32*>(&b)

806:デフォルトの名無しさん
09/10/11 11:00:48
つーかその例でそのエラー出るか?

807:デフォルトの名無しさん
09/10/11 12:29:34
>>804
pin_ptr<int> p = &b;
func(p);

808:デフォルトの名無しさん
09/10/11 13:03:52
>>804
int bがref classのメンバーなのかな。ローカル変数だったら出ないだろ。

809:デフォルトの名無しさん
09/10/11 13:24:52
C++/CLIの仕様書ってある?
C++で言うとISO/IEC 14882:2003みたいな奴

それがあれば簡単な質問ぐらいならC++スレでレスしてやってもよい

810:デフォルトの名無しさん
09/10/11 13:25:46
仕様書じゃなくて規格票だったorz

811:デフォルトの名無しさん
09/10/11 14:14:27
ぐぐるかecma行って372見てこい

812:デフォルトの名無しさん
09/10/11 14:33:33
URLリンク(blogs.wankuma.com)

だめじゃんISO規格じゃない
まあecmaのを参考にするか

813:デフォルトの名無しさん
09/10/11 15:50:25
>だめじゃんISO規格じゃない 

これが言いたかったのか(笑

814:デフォルトの名無しさん
09/10/12 03:21:26
IETF > Ecma > ISO

815:デフォルトの名無しさん
09/10/12 10:19:51
日本の車もウインカーレバーが右で、ISO規格と違うからな。
イギリスは右ハンドルでもISO通りに左なのに。

816:デフォルトの名無しさん
09/10/12 15:25:50
要するにISOってオナニー規格か

817:デフォルトの名無しさん
09/10/13 18:48:03
そういえばC#のコンパイラの言語バージョンを選ぶオプションは
ISO3.0みたいな表記だったな

818:デフォルトの名無しさん
09/10/14 09:55:30
現在自民党が民主党を批判していること、
おまえが言うか、とあきれている。

819:デフォルトの名無しさん
09/10/14 11:20:17
ヤトウの仕事だから。

820:デフォルトの名無しさん
09/10/14 19:29:43
>>818
今まで民主党が批判してた事を民主党がやったりもするわけですよ
ヨトウになるとはそういうこと

821:デフォルトの名無しさん
09/10/14 22:39:15
>>818
スレタイを読めないおまえが言うか、とあきれている。

822:デフォルトの名無しさん
09/10/15 18:55:56
Side-by-sideでexe作ろうとしてるけど
M$っていろんな意味で終わってるなw
保険屋の仕事を作るようにしてあるシステムと同じだろこれw
仕事にしてる奴らは悲惨だろうな。
後には何も残らん。

823:デフォルトの名無しさん
09/10/16 02:11:13
とりあえずMS叩くと出来る奴っぽく見えるよなw

824:デフォルトの名無しさん
09/10/21 01:14:26
エラーがなくせずに困っています。
関数のポインタを渡すときに
error C3867: 'SM::f': 関数呼び出しには引数リストがありません。メンバへのポインタを作成するために '&SM::f' を使用してください
などとエラーになってしまいます。
Move(f);
のfが関数なのですが・・・。
どうすればよいでしょう?



825:デフォルトの名無しさん
09/10/21 09:54:36
ほんとにわかってないのか、これなのかはソース見せてもらわないと判断できないが・・・
URLリンク(msdn.microsoft.com)(VS.80).aspx

826:デフォルトの名無しさん
09/10/21 17:56:32
ダウンロードの詳細 : Visual Studio International Feature Pack 2.0
URLリンク(www.microsoft.com)

827:デフォルトの名無しさん
09/10/21 18:14:59
1.0系でとりあえず行くのかと思ったらいきなり2.0かよw

828:デフォルトの名無しさん
09/10/21 18:34:30
6月の時点で2.0ベータが出てただろ

829:デフォルトの名無しさん
09/11/04 12:57:39
てす

830:デフォルトの名無しさん
09/11/30 21:33:43
TreeViewで追加したノードAとノードAの子のノードBのチェックボックス
にチェックしようと思ったんですが以下のコードではうまくいきませんでした。
各ノードの子が存在するかを調べてチェックする以外の方法でコードがすっきりする方法ありますか?

int countMax = treeView_Action->GetNodeCount(true);
for ( int i = 0; i < countMax; ++i )
{
 treeView_A->Nodes[i]->Checked = true;
}


831:デフォルトの名無しさん
09/11/30 21:42:40
> 各ノードの子が存在するかを調べてチェックする
これで十分すっきりすると思うが
再帰を知らないとか言うのか?

832:デフォルトの名無しさん
09/12/11 16:21:58
どなたかくだすれスレを立ててくだすれ

833:デフォルトの名無しさん
09/12/11 16:33:42
こんだけ過疎ってんだから無駄だろ
聞きたきゃここで聞けばいい

834:デフォルトの名無しさん
09/12/12 02:21:57
失礼します。
Iniファイルの読み書きを行いたいのですが、うまくいきません。
エラーは出ないのですが、ファイルが作成されないので・・・。
すいませんが、どこが間違っているのか教えてください。
よろしくお願いします。

using namespace System::IO;
using namespace System::Text;
using namespace System::Reflection;
using namespace System::Runtime::InteropServices;

[DllImport("kernel32.dll")]
static UInt32 GetPrivateProfileString(String^ lpAppName, String^ lpKeyName, String^ lpDefault, StringBuilder^ lpReturnedString, UInt32 nSize, String^ lpFileName);
[DllImport("kernel32.dll")]
static UInt32 WritePrivateProfileString(String^ lpAppName, String^ lpKeyName, String^ lpDefault, StringBuilder^ lpReturnedString, UInt32 nSize, String^ lpFileName);

// Iniファイル読み込み
private: System::Void IniRead(System::Void){
String^ path = Path::Combine(Path::GetDirectoryName(Assembly::GetEntryAssembly()->Location), L"test.ini");
StringBuilder^ sb = gcnew StringBuilder(1024);
UInt32 ret = GetPrivateProfileString(L"DB_INFO", L"SERVER_NAME", L"default", sb, sb->Capacity, path);
System::Console::WriteLine(sb->ToString());
}
// Iniファイル書き込み
private: System::Void IniWrite(System::Void){
String^ path = Path::Combine(Path::GetDirectoryName(Assembly::GetEntryAssembly()->Location), L"test.ini");
StringBuilder^ sb = gcnew StringBuilder(1024);
sb->Append("TestVal");
UInt32 ret = WritePrivateProfileString(L"DB_INFO", L"SERVER_NAME", L"default", sb, sb->Capacity, path);
}

835:834
09/12/12 02:26:25
開発環境を書くのを忘れてました。
WindowsXP SP3
Visual Stadio 2010 Beta2
です。

836:デフォルトの名無しさん
09/12/12 02:34:25
C++/CLIでわざわざDllImport?

837:デフォルトの名無しさん
09/12/12 08:08:41
/clr:safe なのでは

838:デフォルトの名無しさん
09/12/12 08:25:36
WritePrivateProfileStringの引数がなんでGetPrivateProfileStringと同じなんだよ。
MSDNをみろよ。

BOOL WritePrivateProfileString(
  LPCTSTR lpAppName,  // セクション名
  LPCTSTR lpKeyName,  // キー名
  LPCTSTR lpString,   // 追加するべき文字列
  LPCTSTR lpFileName  // .ini ファイル
);

>>833の手前初心者スレに池とはいえんな(笑


839:デフォルトの名無しさん
09/12/12 13:48:26
初心者スレではCLIスレへ池と言われ
CLIスレでは初心者スレへ池と言われ・・・

840:デフォルトの名無しさん
09/12/12 18:28:17
>>833

斬新だな

841:sage
09/12/12 20:27:27
今まで

Diagnostics::Debug::WriteLine("文字列");
Diagnostics::Trace::WriteLine("文字列");

の違いで Debug は、Debug版コンパイルのみに出力され、
Traceは Debug/Release版 双方で出力される・・・と思って、

Debug::WriteLine("文字列");

を使ってきました。しかし、先ほど

DefaultTraceListener^ dtl = (DefaultTraceListener^)Debug::Listeners["Default"];
dtl->LogFileName = "C:/debug.txt";

としてみると、Release版でも C:/debug.txt に出力されて
しまいました。

Debug版でのみ、出力させるには

#if defined(_DEBUG)
Diagnostics::Debug::WriteLine("文字列");
#endif

としないとダメなのでしょうか?

842:デフォルトの名無しさん
09/12/12 21:21:48
>>841
Conditional属性ついてるから、その認識で間違ってないはずだが

843:デフォルトの名無しさん
09/12/12 21:25:27
Trace::Listeners
Debug::Listeners
は同じコレクションをポイントしていて、片方を変更すればもう片方も変更になる。


844:デフォルトの名無しさん
09/12/12 21:48:40
>>843
そういう問題じゃないだろ

845:デフォルトの名無しさん
09/12/12 21:52:12
>>841-842
C++/CLIではC#やVB.NEtのようにConditionalAttributeを認識しないから、
自分で#ifdef使って、呼び出しを消す必要がある

846:841
09/12/13 01:26:19
>>845

ConditionalAttributeを認識しない・・・んですね。
初耳です。勉強になりました。


>自分で#ifdef使って、呼び出しを消す必要がある

とても面倒ですね。自前のDEBUG関数を定義して、
それでまとめて処理させるべきなんでしょうかね。

847:834
09/12/13 02:10:44
>>838
遅くなってすいません。
無事にできました、ありがとうございます。

848:デフォルトの名無しさん
09/12/13 09:22:00
>>846
関数を使わなくても、#define でいいじゃないか
#ifdef DEBUG
#define DEBUGOUT Trace::~
#else
#define DEBUGOUT
#endif


849:デフォルトの名無しさん
09/12/13 09:28:22
>>846
ちなみに、.NET2からは(Debug|Trace)::WriteLineよりはTraceSourceを使う方がいいことになってる

850:デフォルトの名無しさん
09/12/16 02:13:09
VS 2005で、System::Windows::Forms::ToolStripを継承して、'MyToolStrip' クラスを実装しました。
ビルドすると、ツールボックスの中にMyToolStripが現れましたが、
Formに貼り付けようとすると、

ツールボックス アイテム 'MyToolStrip' の読み込みに失敗しました。アイテムはツールボックスからから削除されます

と表示され、ツールボックスから消えてしまいます。



それならと、既に貼り付けてあるFormクラスの中のToolStripを、MyToolStripへコードを直接書き換えて
みました。コンパイルも通り、実行もできるのですが、FormのデザインをGUIで開こうとすると

デザイナの読み込み時に 1 つ以上のエラーが発生しました。

C++ CodeDOM parser error: Internal Error

が表示され開けません。.NETの標準クラスを継承して、フォームデザイナで使いたいのですが、
どうすれば良いのでしょうか?

851:デフォルトの名無しさん
09/12/16 06:08:01
とりあえず、これで動いてる。どこかで下手打ってるのだろう。
ソースをさらせ。
public ref class MyToolStrip : System::Windows::Forms::ToolStrip { };



852:デフォルトの名無しさん
09/12/16 06:10:35
コンストラクタで例外投げてるとかじゃね

853:デフォルトの名無しさん
09/12/16 08:35:33
これはC#でも同じだが、Controlのコンストラクタに副作用があると
デザーなーの表示に失敗することがあるよ。

854:デフォルトの名無しさん
09/12/16 11:47:21
まあそういう場合は、親がデザイナかどうか判定して挙動を変える必要があるわな

855:850
09/12/16 22:16:49
プロジェクトをWindowsフォームで新規作成して、

>>851

のクラスを定義した所、問題無くツールボックスの中にMyToolStripが現れ、
フォームに貼り付けできました。

プロジェクトのランタイムプロパティが
「純粋 MSIL 共通言語ランタイム サポート (/clr:pure)」の場合問題ありませんが、
当方「共通言語ランタイム サポート (/clr)」で開発をしており、
その場合、850で書いたような状況になります。ノートPCのサブ開発環境でも
再現するので、再現性はあります。

皆さんの所では問題ありませんか?

856:デフォルトの名無しさん
09/12/16 22:18:00
知るか
再現云々言うんだったらまずソースを出せ

857:850
09/12/16 22:31:48
>>856

Windowsフォームを新規作成して、ランタイムを
共通言語ランタイム サポート (/clr)に変更するだけなのですが・・・。

ソースを貼ります。

Form1.h

#pragma once


#include "test.h"

namespace test {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;



858:850
09/12/16 22:32:30
Form1.hの続き
/// <summary>
/// Form1 の概要
///
/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
/// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
/// 変更する必要があります。この変更を行わないと、
/// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
/// 正しく相互に利用できなくなります。
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクタ コードを追加します
//
}


859:850
09/12/16 22:33:28
Form1.hの続き
protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}

private:
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
System::ComponentModel::Container ^components;




860:デフォルトの名無しさん
09/12/16 22:35:58
Form1.h のつづき
#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->components = gcnew System::ComponentModel::Container();
this->Size = System::Drawing::Size(300,300);
this->Text = L"Form1";
this->Padding = System::Windows::Forms::Padding(0);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
}
#pragma endregion
};
}

test.h の中身

#pragma once
public ref class MyToolStrip : System::Windows::Forms::ToolStrip { };

プロジェクトのプロパティでランタイムを共通言語ランタイム サポート (/clr)に変更して
コンパイル。ツールボックスの中にMyToolStripが現れるので、Form1へ貼り付け。

以上です。

861:デフォルトの名無しさん
09/12/17 10:41:25
だらだらコピペするんじゃなくて、再現する最小限のソースを作って貼るんだよ

862:デフォルトの名無しさん
09/12/17 12:30:50
>>861
最小限を貼っているようにしか見えないが。

863:デフォルトの名無しさん
09/12/17 13:33:13
//
//TODO: ここにコンストラクタ コードを追加します
//

864:デフォルトの名無しさん
09/12/17 13:34:51
つーかここでいう最小限は天順とtest.hを貼ればいいだけじゃないかw

865:デフォルトの名無しさん
09/12/17 13:35:17
天順→手順

866:デフォルトの名無しさん
09/12/17 13:37:25
何で貼るのかというと、レスをみた人が追試するためにはるんで
そもそも見る気失せるような書き方しちゃ手伝ってくれる人が減るだけだな。

867:デフォルトの名無しさん
09/12/17 13:39:45
>プロジェクトのプロパティでランタイムを共通言語ランタイム サポート (/clr)に変更して 
ソースが見当たらないが。IDEの制限だったような。pureじゃだめなん?

868:デフォルトの名無しさん
09/12/17 17:14:42
MyToolStripにpublicついてねぇぞ

869:デフォルトの名無しさん
09/12/17 17:42:56
>>868
refクラスではpublicを付けても付けなくてもpublic継承になる。
URLリンク(msdn.microsoft.com)

870:デフォルトの名無しさん
09/12/17 19:53:29
そもそもデザイナってILONLYじゃないアセンブリ読み込めたっけ

871:デフォルトの名無しさん
09/12/17 20:29:01
とりあえずソリューション内に別プロジェクトを作って、
そっちにMyToolStripを作って、メインプロジェクトから参照すれば、
/clr /clr:pure とどちらでもいけた。

872:デフォルトの名無しさん
09/12/23 02:57:12
>>850の問題とは関係ないかも知れないが、
自分もデザイナが見れないエラーに悩まされ、さっき解決したから載せとく。

(12).ToString();

上記のように、ToStringに直値指定するとデザイナが見れなくなる。
コンパイルも通り、実行もちゃんと反映されてるから、見つけるの苦労した

873:872
09/12/23 13:56:38
>>872に追加

InitializeComponent関数内でのToString直値がダメな原因だった。
そもそも、InitializeComponent関数はコードエディタで変更してはいけないらしい

InitializeComponent関数外でToString直値は正常に使える。

874:デフォルトの名無しさん
09/12/29 16:20:36
皆さんはC+/CLIでポインタを宣言する場合、
^や*を型の後ろにつけます?それとも変数名の頭につけます?

書籍等だと以下の形式が多い気がするのですが、
マネージとアンマネージで統一感がとれないような・・

[マネージ]
String^ hoge

[アンマネージ]
char *hoge


875:デフォルトの名無しさん
09/12/29 18:04:35
どっちも型名の直後につけるかな。
アンマネージでは変数の方につける人が多いみたいだけど、
ポインタ型っていう型名だから、変数の側につけるのには違和感があるんだ。

876:デフォルトの名無しさん
09/12/29 19:05:33
C#では構文上も型名の一部ということになってる
int *x, y, z;
と書くと全てポインタになる

877:デフォルトの名無しさん
09/12/29 21:16:52
>>875
>>876
C++/CLIだと型名の一部にはならないよね?
例えば以下のコードはコンパイルエラーとなる。

class Hoge{};

int main()
{
Hoge* x,y;
x= new Hoge;
y= new Hoge;//yがポインタとして認識されないため、コンパイルエラー
return 0;
}

CとかC++と同じ仕様なんだろうけど、
ポインタ型っていう考えでいくとなんでコンパイルエラーとなるのかが説明できない。
C#が特殊な気がする。

878:デフォルトの名無しさん
09/12/29 21:33:01
なんかCLIやってる人って可哀想だね

879:デフォルトの名無しさん
09/12/29 21:53:43
C/C++の構文がおかしいだけで意味上はポインタ型
不自然なのは誰の目にも明らかだからわざわざC#では変えたんだろ
どっちでもいいけどマネージとアンマネージで変えたりせずにどっちかに統一するべき

880:デフォルトの名無しさん
09/12/29 22:33:26
「つもり」は「意味」にならんだろ

881:デフォルトの名無しさん
09/12/29 23:18:54
ならんだろうね

882:デフォルトの名無しさん
09/12/30 00:11:42
あの記法でポインタを表そうとすると、
関数ポインタ型を表す場合、型の方に*をつけることは出来ないので、
変数の方に*をつけてポインタを表すというのは一定の合理性がある。

883:デフォルトの名無しさん
09/12/30 02:07:27
一定の合理性があるな。

884:デフォルトの名無しさん
10/01/02 10:56:36
CLIでcallocするとどうなるの?

885:デフォルトの名無しさん
10/01/02 11:50:26
普通にアンマネージヒープが割り当てられるだけ

886:デフォルトの名無しさん
10/01/03 18:49:18
当初VB.netで作った業務アプリをVC++/CLIに移植したのですが、
実行速度もメモリ使用量も違いがあるようには思えず、
WinXPだとVC++のランタイムが別途必要になった分、劣化したような気にすらなるのですが、
VC++/CLIの利点って、上達すれば業務アプリでもあるものなのでしょうか?

887:デフォルトの名無しさん
10/01/03 19:19:16
ない
既存のアンマネージコードをマネージコードと混ぜるためだけに仕方なく使う言語
その場合も使用範囲は最小限に留めて,できるだけVBやC#で書くようにするのが正しい

888:デフォルトの名無しさん
10/01/03 20:26:51
gcnewをなめるなよ

889:デフォルトの名無しさん
10/01/03 20:49:08
MS自身ですら避けてるからな
マネージからアンマネージ→DllImport
アンマネージからマネージ→CLRのホスティング

890:デフォルトの名無しさん
10/01/03 22:27:46
XNAくらいだっけ、MS製で使ってるの

891:デフォルトの名無しさん
10/01/06 21:01:42
CLI 使ってる時点で速さが変わらないのは当たり前
アンマネージドコードを利用しないと速くなる訳が無い

892:デフォルトの名無しさん
10/01/06 22:16:08
新規にアンマネージコード書くなら普通のネイティブなDLLとして作ってC#からDllImportする形の方が扱いやすい

893:デフォルトの名無しさん
10/01/07 20:22:39
XNAってなんで早く動くの?

894:デフォルトの名無しさん
10/01/07 21:01:54
ゲームってDirect3Dに描画命令を送ってからの内部の処理が重くてボトルネックになるので
C++/CLIを挟もうがゲームロジックがマネージコードで書かれてようがあんまりパフォーマンスに影響しない

895:デフォルトの名無しさん
10/01/15 20:33:57
ネイティブのアプリケーションがプラグインに飛ばしてくるコールバックを拾って、
それをC#に渡して処理するアプリケーションを書きたいのですが、
その辺のノウハウについてまとまっている情報源をご存知の方はいませんか?

896:デフォルトの名無しさん
10/01/15 20:47:27
イベントかインターフェイス経由でC#にそのまま流せばいいだけでしょ
全く悩むところなんかない

897:デフォルトの名無しさん
10/01/15 21:00:14
>>896
C++/CLIで書いたコードって、普通にやるとマネージコードにコンパイルされると
思っていたのですが、ネイティブから呼ばれても大丈夫なのでしょうか。

898:デフォルトの名無しさん
10/01/15 21:05:35
/clr なら相互に呼び出し可
/clr:pure の場合、マネージドコードからネイティブ方向の呼び出しは可
/clr:safe の場合、不可、ただしP/Invokeは可能。

Win32APIのコールバックを直接C#で処理したいなら、
特殊なものでなければ、P/Invoke+Delegateで対応可能。

899:デフォルトの名無しさん
10/01/15 21:11:21
最悪COM経由でどうとでもなる

900:デフォルトの名無しさん
10/01/15 21:20:41
>>898
分かりやすい解説感謝します。
そういうことなら、普通にアプリ指定のコールバック関数を定義して、
そこからC#のコードを呼べばよさそうですね。ありがとうございます。

901:デフォルトの名無しさん
10/01/15 23:01:30
教えてください。

まず、VC2003 で作った一部マネージコードの混じったアンマネージの .lib ファイルがあります。
これを(ちょっと事情があって) VC2003 でアンマネージの .dll にくるみました。
で、これを(さらに事情があって) VC2008 の C++/CLI でマネージの .dll に
DllImport を利用してラッピングしようとしています。

ここで、ライブラリとして公開する関数はいくつかあるのですが、その中にパラメータとして
構造体を参照形式で持つモノがあります。
構造体の中には std::string で定義した要素を持つモノもあるのですが、これを先のアンマネージの
.lib の関数内で参照したり変更したりするとアクセスバイオレーションで不正終了することがあります。
同じ構造体内の int 型などの要素の値を参照/変更しても変な値が入ることがあります。
そこで、この構造体の std::string 型の要素を char[] 型に変更して試したところ、特に問題なく期待通りの動作をしました。
マネージ dll を介さずに、アンマネージの .dll を使用する分には元のままでも問題なさそうです。

この原因ってなんでしょうか。
また、回避方法があれば教えていただけないでしょうか。

902:デフォルトの名無しさん
10/01/15 23:03:11
ゲームでCOM経由はどうなんだろう
DllImport、P/Invoke+Delegate とは違うんだよね
どんな時に使うんだろう…どう使い分けるのかの時点で悩みそうだ…

903:デフォルトの名無しさん
10/01/15 23:18:09
>>901
そんな使い方するのがおかしい。
C++/CLIでアンマネージドとマネージドを混ぜたら、あとはマネージド側から使うだけ。

904:デフォルトの名無しさん
10/01/15 23:24:50
>>901
真っ先に思い浮かぶのは、メモリ確保周りの問題。
2つのDLLでstd::stringが同じメモリ確保ルーチンを使うようにしてみたらどうなる?
例えば、両方でグローバルなnew/delete演算子関数を定義するとか。
#include <new>
void* operator new(std::size_t n)
{
if (void* p = HeapAlloc(GetProcessHeap(), 0, n))
return p;
else
throw new std::bad_alloc();
}

void operator delete(void* p)
{
if (p != 0)
HeapFree(GetProcessHeap(), 0, p);
}
std::stringに対して自前のアロケータを指定するというのでもいい。

905:デフォルトの名無しさん
10/01/15 23:42:18
VC2003ってことはManaged C++か

906:デフォルトの名無しさん
10/01/15 23:54:56
>>901
C++/CLI以前の問題じゃないか、それ

基本的にDLL境界をまたいで、FILE*のようなCランタイムオブジェクトや
malloc()/newで確保されたメモリ渡すときは要注意
Aで確保されたメモリをBで開放するときは、モジュールAとBが同一の
ランタイムにダイナミックリンクしてないと即終了
C++のstd::stringなんぞをインタフェースに使ってたらそういうことは
当たり前に起きる

>>904の指摘はそれを前提にしている訳だが、
C++標準ライブラリクラスは、そもそも実装の大半がヘッダにあり、
バージョンが違えばそのバイナリ互換性すら怪しい
俺はそもそも設計として、C++標準ライブラリクラスをDLLインタフェースに
使うことは全くオススメしない
設計を見直すべき

907:デフォルトの名無しさん
10/01/16 00:13:38
>>904
URLリンク(developer.apple.com)
URLリンク(ameblo.jp)

調べてみた。部分的なら書き換えおkだけど
標準部分の書きかえはそれなりに茨の道な気がする…

908:デフォルトの名無しさん
10/01/16 16:48:20
C++/CLIも.NET総合もくだすれが発見出来ないので、おそるおそるここで聞かせて頂きます。

DLLを制作しているのですが、DLL中からフォームを呼び出すレベルで詰まっています。
DLL自体は動的に外部の別のDLLから呼び出され、初期化関数が走らされる感じで、

IDEからWindowsフォーム(CLR)を追加し、フォームを何も弄らない状態で
DLLの初期化関数中で(gcnew hoge::hogeForm())->Show();
しているのですが、Showの呼び出し中に固まってしまいます。
メッセージループが存在しないせいかと思い、Application::Run();してから
Showしても同様です。

通常のexeを作成し、メインウィンドウのインスタンスをもう一つ同様にShowしようとしても
同じく死んだので、何か初歩的なレベルでミスしているのだと思うのですが、
エスパーしていただけないでしょうか……。


909:デフォルトの名無しさん
10/01/16 16:54:28
Application::Run(gcnew hoge::hogeForm());

910:>>901
10/01/16 18:05:57
>>903-907 のみなさま、ありがとうございます。

特に >>906 さん。なんとなくわかってはいたのですが、言葉できっちり表現がされていて助かります。
>>904 さんの方法も試した上で、週明けに改めて説明を行って対応方法を変更する方向で動きます。

911:デフォルトの名無しさん
10/01/16 19:44:08
>>908
(gcnew hoge::hogeForm())->Show(); じゃフォームのハンドルを押さえているヤツが居ないな

912:デフォルトの名無しさん
10/01/16 22:48:45
Formは表示中GCの対象外になるようになってる

913:908
10/01/17 04:44:50
>>909
>>911-912
どうもありがとうございます。
Application::Run(gcnew hoge::hogeForm());も試して見ましたが、同様にそこで処理が止まります。
(次の行でデバッグ用の出力を入れていますが、出力されません)

ネイティヴ関数の状態から(CLRでない空のプロジェクトにグローバル関数を置いた状態から)、
/CLRを追加し、Windowsフォーム(CLI)の追加、
グローバル関数を記述したcppからのmscorlib.dllやフォームのヘッダの参照、
Application::Run(gcnew hoge::hogeForm());と、やっていることはこれだけで、
以下のような感じです。

#include <windows.h>
#using <mscorlib.dll>
#include "hogeForm.h"
int __stdcall Init() {
Application::Run(gcnew hoge::hogeForm());
}

ManagedとUnmanagedの区分け等、何か気を遣うところがあるでしょうか。


914:デフォルトの名無しさん
10/01/17 05:09:13
>>913
Init()を呼び出す。
フォームが表示される。
フォームを表示したままinit()が終了して呼び出し元に戻ってくる。
というのを期待しているとかしてないよね?


915:908
10/01/17 05:15:53
>>914
フォームが表示されることは期待しています。
上のコードでは、フォームを終了しない限り、処理が呼び出し元に返ってくることは期待してません。


916:デフォルトの名無しさん
10/01/17 05:18:14
とりあえずこれで動いてる
// testd8.cpp managed
#using <System.dll>
#using <System.Windows.Forms.dll>
using namespace System;
using namespace System::Windows::Forms;
void Init() {
  Application::Run(gcnew Form);
}
// testd9.cpp native
void Init();
int main() {
  Init();
  return 0;
}

cl /clr /c  testd8.cpp
cl /MD testd9.cpp testd8.obj


917:908
10/01/17 18:35:12
>>916
同等の物を書いてみましたが、確かに動作しています。
呼び出し方法やら何やら、片っ端から確認していって、原因を特定しようと思います。
どうもありがとうございます。


918:デフォルトの名無しさん
10/01/17 22:05:10
汎用的なDLLでいきなりApplication::Runとかされたらヤだな

919:デフォルトの名無しさん
10/01/21 22:57:19
質問ですが、
タイトルバーがなく3Dの縁があるフォームを作るには
どうすればいいのでしょうか。
環境はVC++2008です。
フォームのプロパティ設定の中には見つかりませんでした。


920:デフォルトの名無しさん
10/01/22 00:10:35
C# タイトルバー 消す
とかでググれば一発
調べても分からない場合でもそういう質問はC#かVBスレでしたほうがいい

921:デフォルトの名無しさん
10/01/22 21:52:51
>>920
なるほど、.NETなら共通なんですね。
わかりました、ありがとうございます!


922:デフォルトの名無しさん
10/01/23 11:53:50
Visual Stuidion C++ 2008での書き方を教えて。

フォームクラスだと、イベント関数とかすべてヘッダの方に生成されるけど、
独自メソッドもすべてヘッダーの方に書くものなの?
それともプライベート関数はcppの方に書くとかルールがあるの?


923:デフォルトの名無しさん
10/01/23 16:01:29
俺はヘッダは宣言のみにして、ソースファイルに定義。プロパティも同じ。
全部ヘッダに書いて、cpp削除でもいいんじゃね?w

924:デフォルトの名無しさん
10/01/23 20:14:29
自分もそうかな。プロパティはヘッダに書いちゃうこともある。
C# とかは分かれてないからどっちでもいいと言えばいいんだと思うけど、C/C++ の伝統がそうさせる。w

925:デフォルトの名無しさん
10/01/24 16:24:16
.NET言語って全部コンパイル速いからな~、ヘッダに書いといて無駄なコンパイル発生しても
ほとんど気にならないレベル

926:デフォルトの名無しさん
10/01/26 00:04:55
temp_buf[TEMP_BUF_SIZE], temp_buf2[TEMP_BUF_SIZE]は'\0'で初期化されてます。
文字列がtem_bufに格納され、その中から"search"を探索し、文字列が見つかれば
そのsearchのs以降の文字をtemp_buf2にコピーしようとしています。
が、実行すると暴走してしまいます。
*pの使い方がおかしいような気もするんですが、
原因が分かりません。
環境はgccですが手元にpcが無いので詳細は分かりません。
もし必要でしたら調べてきます。ごめんなさい。

char com[] = "search";
char *p = strstr(temp_buf,com);
if( *p != NULL ){
if( sizeof(temp_buf2) - &(temp_buf[TEMP_BUF_SIZE-1])-&(*p)+1 < 0){
fprintf( stderr, " buffer overflow 1\n" );
exit(-1);
}
strcat( temp_buf2, p );
printf("%s",temp_buf2);
 }

よろしくお願い致します。


927:デフォルトの名無しさん
10/01/26 00:13:34
>>926
>>1

928:デフォルトの名無しさん
10/01/26 00:23:02
スレチですね
失礼します

929:デフォルトの名無しさん
10/01/26 00:26:06
>>928 は
>>926
のことです

930:デフォルトの名無しさん
10/01/26 22:01:38
VC++ 2008 ExpressEdition で Form::Controlクラスを継承した独自コントロールクラスに
枠をつけるにはどうすればいいのでしょうか?
プロパティ設定には境界線の項目がありません。
それらしきメソッドも見当たりません。誰か知っていたら教えてください。

931:デフォルトの名無しさん
10/01/26 22:06:43
>>930
ほい。
URLリンク(uchukamen.com)

932:デフォルトの名無しさん
10/01/26 22:14:16
>>930
VisualStyleRenderer使って自前で描画する
プロパティも自分で実装する
あと>>920の3行目

933:デフォルトの名無しさん
10/01/26 22:19:28
要するに、
コモンコントロールのそれぞれは自前で描画していたんですね。。
良く分かりました、ありがとうございます。

934:デフォルトの名無しさん
10/01/26 22:23:25
>>933
Windowsで動作するほぼ全てのウィジェットレンダラーは
Win32GDIをまとめ直したものに過ぎないんだが、
最近の人はWin32APIで直接アプリを作ったりする経験がないから自前で描画する、という感覚がつかみにくいのかもしれんねぇ。

それはそうと、コントロール描画くらいならC#で実装した方が簡単だよ。

935:デフォルトの名無しさん
10/01/26 22:30:26
>>934
動作のコアとなる部分がC++で作ってあって、DLLとしてまとめてあるんだけど、
GUI側をC#で作るとなると、呼び出すのに定義作り直すのがめんどうで、
どうしてもこの言語に手を出さざるをえないのよね。

936:デフォルトの名無しさん
10/01/26 22:32:56
>>935
ええー。今時、WindowsでGUIを書くのにC++を使うなんて、マゾとしか思えん。
逆ならわかるがねぇ。
GUIをC#で書いてモデルや下回りをC++でってなら。

937:932
10/01/26 22:36:49
すまん枠描くのはControlPaintだった
よっぽど深い相互運用しない限りはexport/DllImportの手間を差し引いてもC#の方が楽だし
安全だし取り回ししやすいよ

938:935
10/01/26 22:44:13
>>936-937
むう、再検討します。


939:デフォルトの名無しさん
10/01/26 22:58:32
いわゆる普通の ウィンドウ枠は WS_BORDER だぞと。
普通は CreateParams オーバーライドして Style プロパティに
WS_BORDER のビットフラグ立てたのにするだけ。
3D 枠とかも基本は一緒な

940:デフォルトの名無しさん
10/01/26 23:04:22
いやWindowsネイティブのコントロールに対応しない独自描画のカスタムコントロールの場合は
枠も自分で描くべき
標準のコントロールもそうなってる

941:デフォルトの名無しさん
10/01/28 10:27:29
そもそもコモンコントロールだってただの画像だしな

942:デフォルトの名無しさん
10/01/29 00:20:52
C++/CLI と C# embedded C++ どっちがいい?

943:デフォルトの名無しさん
10/01/29 00:48:20
3択な上に比較対象がおかしい。

944:デフォルトの名無しさん
10/01/29 02:04:59
何がしたいのかも判らんのに「どれがいい」も糞もないけどな。
WM (CE) の話で C++/CLI or C# or eVC++ のどれか、っていうなら
…いや、やっぱり好きにしろとしか言えないw

945:デフォルトの名無しさん
10/01/29 02:46:25
(C++ in C#) の意味では?

946:デフォルトの名無しさん
10/01/29 09:39:46
>>942-943
ワロw

947:デフォルトの名無しさん
10/01/31 03:31:10
これからはC++0x/CLIの時代だろ

948:デフォルトの名無しさん
10/01/31 05:14:01
敵はObjective-C++0xだな

949:デフォルトの名無しさん
10/01/31 06:53:39
今までC++とC#ばかりいじくっていたが、Google様にお伺いを立てると
実行速度は

C++ > C++/CLI > C#, VB.NET らしい

C++/CLIの方が効率よく高速なMSILに変換される仕組みでもあるのかな?

950:デフォルトの名無しさん
10/01/31 11:12:50
無いし実際同じ

951:デフォルトの名無しさん
10/01/31 11:22:21
C++/CLI はネイティブコードで書いた部分の実行速度が速いからとかじゃ?

952:デフォルトの名無しさん
10/01/31 11:38:51
ボックス化された値型とかトラッキング参照とか駆使して低レベルな最適化をやれば速くなるかもしれないけど
JITのバージョンアップであっさり逆転したりしそうだ

953:デフォルトの名無しさん
10/01/31 22:47:30
検証に使用したコードがないと話にならんだろ。

954:デフォルトの名無しさん
10/01/31 22:51:54
C#よりもC++/CLIの方ができることの制限が少ないから、速いコードを書くこと余地は大きいだろうね。
C++はUnsafeだから、こういうのを単純に比較しても意味ないと思うんだけどな。

955:デフォルトの名無しさん
10/01/31 23:03:35
一般に将来的な最適化の妨げになるしなあ

956:デフォルトの名無しさん
10/02/01 03:06:48
C++/CLIの速さはこの2つを足して2で割ったところとしているんでしょ。
マネージ部分の速さ = C#, VB.NET
ネイティブ部分の速さ = C++

957:デフォルトの名無しさん
10/02/01 09:17:41
まあアンマネージだけで書いたらC++もC++/CLIも変わらんわな
マネージだけで書いたらC++/CLIもC#も変わらんわな

測ってないけど

958:デフォルトの名無しさん
10/02/01 10:42:19
くだすれ落ちているのでここで失礼します。

unmanagedなバイト配列(unsigned char* byteArray, int len)を
managedな配列(array<Byte>)に変換したいと考えています。
とりあえずインデクサをつけて一個一個代入していったり、
Addしてみたりしたのですが、随分と処理に時間を喰ってしまいます。
そこまで速度に神経質なプログラムでも無いのですが、
もっとスマートに配列を変換する方法は無いものでしょうか。


959:デフォルトの名無しさん
10/02/01 11:29:42
Marshal.Copy(IntPtr, byte[], int, int) とか。

960:958
10/02/01 12:04:10
>>959
Marshal探せば良かったんですね。
Managedメモリを固定して確保してからmemcopyとか、明後日の方向に向かって努力していました……。
どうもありがとうございました。


961:デフォルトの名無しさん
10/02/02 03:10:27
C++/CLIは/clr /clr:pureでは常にunsafeであり、
Cタイプの配列を使った場合のパフォーマンスが良い。1~2割程度。
C++/CLIの暗黙のP/InvokeはSuppressUnmanagedCodeSecurityAttributeがデフォルトでオンなので、
C#のP/Invokeに対してパフォーマンスが良い。2~3倍程度。
C#のP/InvokeにSuppressUnmanagedCodeSecurityAttributeを追加するとその差はなくなる。
またC++/CLIのリンク時に/CLRUNMANAGEDCODECHECKを付けると、
この属性がオフになるためパフォーマンスはC#と変わらなくなる。


962:デフォルトの名無しさん
10/02/02 21:49:51
C#でも一応スタックに配列取ったりマネージ配列やアンマネージ配列にポインタでアクセスしたりできるよ

963:デフォルトの名無しさん
10/02/02 22:10:43
マネージドで書いとけばいいのにやたらアンマネージド呼び出して
結果マーシャリングコストばっかりかかってパフォーマンス悪化とか、ありそうな話


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch