X



くだすれC++/CLI(初心者用)part2
レス数が950を超えています。1000を超えると書き込みができなくなります。
0001./1256645713/662
垢版 |
2010/03/15(月) 09:41:19
おそらく、.NET開発でデファクトスタンダードに最も近いであろう
C++/CLIについて語ろうぜ!

このスレはC++および.NET Frameworkについて一定以上の知識を持っている人が対象となります。
.NETのクラスライブラリの使い方といった質問は Visual Studioスレにお願いします。

前スレッドはこちら
くだすれC++/CLI(初心者用)
http://pc8.2ch.net/test/read.cgi/tech/1142144110/l1

dat落ち姉妹スレ
C++/CLI part3
http://pc12.2ch.net/test/read.cgi/tech/1206447234/l1
http://pc11.2ch.net/test/read.cgi/tech/1142147319/l1
http://pc8.2ch.net/test/read.cgi/tech/1126450441/l1

managed C++ やろうぜ!! 002
http://pc8.2ch.net/test/read.cgi/tech/1139043535/l1
0851デフォルトの名無しさん
垢版 |
2014/06/25(水) 19:43:48.20ID:a/L3Ky6p
なんでご愁傷様?
0852デフォルトの名無しさん
垢版 |
2014/06/29(日) 15:12:56.12ID:74KQZ/Pg
WebBrowser::ActiveXInstanceのようなCOMポインターをObject^で返したいんですが
どう書いたらいいんでしょうか

Object^ get()
{
IUnknown* pU; //これを返したい
...
}

C#だと全部属性でやってて生ポインタをどう処理するかの参考にならないです。
0853デフォルトの名無しさん
垢版 |
2014/06/30(月) 07:13:06.08ID:AE59suyp
それを返した先でどうするのさ
例えばIntPtrを返しても一応Object^にはなるけど多分そういう事じゃないよね?
0854デフォルトの名無しさん
垢版 |
2014/06/30(月) 08:29:40.70ID:k6aB52Mb
Object^o=Marshal::GetTypedObjectForIUnknown(IntPtr(pU),Object::typeid);
とりあえずこうしました
addref,releaseが同じにならないといやだけど
0855デフォルトの名無しさん
垢版 |
2014/07/30(水) 21:04:47.45ID:4VkY0HvI
C++/CLI超楽しい
.Net、WinAPI、STL、Boost混在できて使いたい放題だし
何でみんな毛嫌いするの?
0857デフォルトの名無しさん
垢版 |
2014/07/30(水) 23:48:31.72ID:QJA3s1XV
最初から別言語だと思っとけばいいじゃん。
俺もC++/CLIは面白いと思うが、先がなさそうなのが残念だな。
WPFが使えるようになったらMFCのアプリを移行したいと思っていたんだが。
0858デフォルトの名無しさん
垢版 |
2014/07/31(木) 13:36:46.98ID:N7h43RT+
やりたい放題というのは1人でやってるだけなら楽しいが
足を引っ張る仲間がいると地獄巡り満腹コースになる
0859デフォルトの名無しさん
垢版 |
2014/07/31(木) 20:54:03.92ID:Ng6XWAlf
マネージ関数の中でlambda使えないとか、最近は混ざる利点みたいなものが少なく…。
0860デフォルトの名無しさん
垢版 |
2014/08/05(火) 16:06:10.29ID:8/O3Z/TB
genericとtemplate混ぜたら楽しいと思ってたけど、
あんまり混ざらないようにできてる・・
0861デフォルトの名無しさん
垢版 |
2014/08/05(火) 21:42:31.92ID:a3vuC94X
variadic template使って型パラメータの数が違うgeneric classを使えるかと思ったら、なんかエラーになるしね。
0862デフォルトの名無しさん
垢版 |
2014/08/06(水) 12:55:33.48ID:YJYkBYpf
genericクラスの中にtemplateは作れないし
その逆もできない。
できるのは、genericクラスをtemplateで
継承するくらい。

>>861 variadic genericあったらいいなぁ
0863デフォルトの名無しさん
垢版 |
2014/09/26(金) 00:00:55.65ID:Q/qK3xNe
C++/CLIに直接関わる質問ではないのですが
適切なスレが見当たらなかったのでここで質問させてください。

ネイティブのnative.dllをマネージのmanage.dllが参照しているとき
native.dllにパスが通っていない状態でmanage.dllを使用すると
FileNotFoundExceptionが発生してしまいますが、
その例外の値からはnative.dllが見つからないことが原因であることを
判断することができません。

そこでmanage.dllが参照しているdllの一覧のようなものを取得したいのですが
そのようなAPIは用意されていますでしょうか?
とりあえずdumpbin.exe /dependentsで出力される結果を用いる実装にしてみたのですが
やはり外部の実行ファイルに頼るのは微妙ですし、何より処理が重いです。
Win32APIでも構いませんので何か方法がありましたらご教示ください。
0866デフォルトの名無しさん
垢版 |
2014/09/26(金) 11:29:52.72ID:b/KTTsk9
FileNotFoundが発生したら
LoadLibrary("native.dll");
GetLastError()してみるってのはどうだろう?
0867デフォルトの名無しさん
垢版 |
2014/10/08(水) 22:50:24.63ID:T8t7hCtu
>>863です。亀ですいませんが解決しました。
APIとしてはImageHelpライブラリ辺りが使えそうだったのですが途中で詰まったので断念。
結局ファイルを直接読んでIMAGE_DOS_HEADER構造体からたどって
インポートデータを解析することで対応できました。
0868デフォルトの名無しさん
垢版 |
2014/10/16(木) 17:29:15.53ID:sLOsTk32
質問です。

MyCapsuleというクラスを作り、GetValue(参照渡しの引数)という仮想関数を
定義しておいて、このクラスから派生したクラスにおいてGetValueの実装を
するにあたり、与えられた引数がある特定の型に合致する場合にはその
引数に値を代入する、という動作を実現したいです。
例えばMyCapsuleIntという派生クラスでは、与えられた引数がint型だった
場合に、その引数に(何かしらメンバ変数などの)値を代入する、というもの
です。

こういう場合アンマネージドだと引数としてvoid*を使った実装になるかと
思うんですが、マネージドだとかわりにObject^%とかを使うのでしょうか?
ハンドルと追跡参照について未だによくわかっていないので、どうするのが
一般的な作法なのか見当がつきません。

よろしくお願いします。
0869デフォルトの名無しさん
垢版 |
2014/10/16(木) 21:50:11.68ID:rtOJWyFH
アンマネージからマネージの関数を呼んで
マネージドの中で作ったString^からchar*でアンマネージドに戻したいんです。

調べたところ
(char*)Marshal::StringToHGlobalAnsi("").ToPointer()ってのがあるのはわかったのです。
けど、これで戻してもアンマネージドからMarshal::FreeHGlobalが呼べないのでだめです。
一度StringToHGlobalAnsiで得たchar*を別のcharのバッファにコピーしてから戻す方法になるのでしょうか。
0870デフォルトの名無しさん
垢版 |
2014/10/16(木) 22:01:55.82ID:rvFRd6iT
Marshal::StringToHGlobal...で確保したのはLocalFreeすればいいけど
普通は呼び出し元がバッファ用意するなり、std::stringとかで返すなりするもんじゃね?
0871デフォルトの名無しさん
垢版 |
2014/10/16(木) 22:15:47.60ID:rtOJWyFH
なるほどLocalFreeで解放できるんですね。

>普通は呼び出し元がバッファ用意するなり
固定長になるからどうしようかなとおもって。

>std::string
StringToHGlobalAnsiで領域を確保したのに
stringでまた確保されるのがあれかなとか。
気にしすぎといわれればそうです・・・。
0872デフォルトの名無しさん
垢版 |
2014/10/22(水) 13:38:11.49ID:5iN2ViqP
C#みたいにCodeProviderで動的な文字列をコンパイルして
実行したいんですが、もしかしたらC++/CLIにはCodeProviderが
ないですか?
0875デフォルトの名無しさん
垢版 |
2014/11/11(火) 14:49:35.49ID:TsA8Knwq
C++のDLLをC#で使いたいのですがC++/CLIで吸収したほうがいいのかな?
C++の構造体のポインタとかあってわけわからん
0877デフォルトの名無しさん
垢版 |
2014/11/12(水) 00:51:06.13ID:pdAxKpZn
>>875の件ですがC#でなんとかがんばることにしました
お騒がせしました
0878デフォルトの名無しさん
垢版 |
2014/12/09(火) 00:10:16.60ID:xpR1dfQS
C++/cli からC++のプロジェクトに定義している関数を呼び出したいんです。
C++プロジェクトのlibファイルを参照し、includeファイルをC++/cli側に
持ってきて#include すると、物凄い数のエラーがでます。

(C2011:C2079:C2504:C3395:C3699)

[1] C++/cliで参照できるよう、ビルドエラーを直すしかない

[2] 別の方法でC++の関数をビルドエラー無しに参照できる。

ちなみに、C++の関数を参照しないで自作・・・という回答は無しでお願いします。
0879デフォルトの名無しさん
垢版 |
2014/12/09(火) 10:30:47.48ID:sSNN3cut
物凄い数のエラーじゃなくてエラーの内容をチェックしろよ。
出力ログのエラーの行をダブルクリックすると問題の箇所に飛ぶから
何で再定義だとか定義がないと言われてるか考えろ。
何でその程度のレベルでC++/CLIとかやってんの。
0880デフォルトの名無しさん
垢版 |
2014/12/09(火) 10:30:56.11ID:Xzj5HeMN
1.C++から呼び出す
2.C#に移植する

C++/CLIでなきゃいけない理由なんてあるん?
0881878
垢版 |
2014/12/09(火) 22:59:58.60ID:ygQnozb4
すみません、初心者なりにエラーの原因を調べてきました。

a.h

class A : public B {}

b.h

class B {}



この時に Class B で再定義のエラーが発生していました。

a.h が先にincludeされているのが問題で、b.h を先にinclude するよう
ソース修正すれば良い・・・・・ということでしょうか??
0882デフォルトの名無しさん
垢版 |
2014/12/11(木) 12:05:51.55ID:WAwY/dPu
各ヘッダの先頭に#pragma onceと書く

a.hでb.hのクラスを使っているなら
a.h内でb.hをinludeしろ

cpp側でincludeの順を気にしなきゃならないのは糞
0883デフォルトの名無しさん
垢版 |
2014/12/15(月) 20:00:30.77ID:JoQajMNA
質問です。

任意の型のマネージド配列(cli::array)を、任意の個数、引数として受け取って
それらの配列としての長さの最小値を返す関数を書きたいと思っています。

イメージとしては、
array<String^> arrStr = gcnew array<String^>(6);
array<double> arrDob = gcnew array<double>(8);
array<int> arrInt = gcnew array<int>(3);
に対して、
Function(arrStr, arrDob) = 6
Function(arrStr, arrDob, arrInt) = 3
となるような関数Functionを書きたいと思っています。

しかし、この場合の引数リストの書き方がよくわかりません。
単純に可変長の引数リストだとFunction(... array<Object^>^ args)みたいな
書き方になると思うんですが、これをマネージド配列の配列だからといって
真似てFunction(... array<array<Object^>^>^ arrays)みたいな書き方をしても、
呼び出し側(例えばFunction(arrStr, arrDob)とか)で引数リストが一致しない旨
怒られます。このような場合の適切な引数リストの書き方ってありますか?

あるいは回避策として、引数はFunction(... array<Object^>^ args)としておき
この関数の中でfor each (Object^ arg in args) { argが配列かどうか }という
コードもありえますが、肝心の、「argが配列かどうか」チェックするコードが
わかりません。

上記いずれか一方で構いませんので、解決策をご教授いただけないでしょうか?
0885デフォルトの名無しさん
垢版 |
2014/12/15(月) 22:28:59.04ID:JoQajMNA
>>884
試してみましたが、いずれの場合もコンパイルエラーC3132が発生します。

そもそもargの型を何に指定すべきなのか、というのがよくわかっていません。
例えば
int Function(... array<Object^>^ args)
{
  int MinLength = -1;
  for each(array<Object^>^ arg in args)
  {
    if ( (MinLength < 0) || (arg->Length < MinLength) )
    {
      MinLength = arg->Length;
    }
  }
  return MinLength;
}
みたいなコードだと、Function(arrStr, arrInt)を実行したとき、それら引数を
System.Object[]にキャストできない旨を怒られます。
0886デフォルトの名無しさん
垢版 |
2014/12/15(月) 22:43:22.71ID:oSpn/+/y
ごめんちょっとぼけてた
... array<System::Array^>^ args
for each (auto arg in args) { int len = arg->GetLength(0);
... array<System::Collections::IList^>^ args
for each (auto arg in args) { int len = arg->Count;
0887デフォルトの名無しさん
垢版 |
2014/12/15(月) 22:49:54.98ID:JoQajMNA
>>886
うまくいきました!
動作版のコードは以下の通りです。

int Function(... array<System::Array^>^ args)
{
  int MinLength = -1;
  for each(auto arg in args)
  {
    if ( (MinLength < 0) || (arg->Length < MinLength) )
    {
      MinLength = arg->Length;
    }
  }
  return MinLength;
}

ありがとうございました。
0892デフォルトの名無しさん
垢版 |
2015/03/01(日) 13:44:47.71ID:M4V41Yry
既存の native C++ のプログラムからC#で作ったdllを呼び出す必要が出てきたんで
/clrを使おうと思うんだが、.NETを使う部分以外のソースを全部 #pragma unmanaged
しておけば既存のnativeのプログラムと変わらないと考えていいのかな?
スタートアップに時間がかかったりするかもしれないけど。
それ以外になにか、純粋なnativeアプリと比べてのデメリットとかあるだろうか?
0894デフォルトの名無しさん
垢版 |
2015/03/03(火) 22:20:54.28ID:QODsipDB
COMはregistryやGACに登録しないとならないのが。それがなければ使いたいんだけど。
pragamはまぁ、stdafx.hに仕込んどけばいいだけなんで。
で、試してみて一応ビルドは通って、DependencyWalkerで見てもほとんど同じに見えたけど、
起動時に例外が出てうまく立ち上がらなかった。
どちらにしても、ビルドに時間がかかるんで普通にwrapperだけC++/CLIで作った方が楽そう。
0897デフォルトの名無しさん
垢版 |
2015/04/11(土) 23:36:34.69ID:rfVEU9W7
http://peace.2ch.net/test/read.cgi/tech/1420379468/279
から誘導されてきました。

質問です。

実行時にフォームをイベントごとコピーしたいのですが、
元のイベント関数のハンドラが取れず、上手く行きません。
解決策があれば教えてください。

やりたいこと:
チェックボックス等のフォームをデザイナで指定し、イベント関数もデザイナで指定します。
プログラムでこのチェックボックス等を10個ほどにコピーし、並べます。
このときにプロパティ等はコピーできますが、イベント関数がコピーできません。

理由:
位置決めが楽なので、デザイナ側で頭のFormは指定したいのです。
そして管理上分かりやすいので、イベントもそこに書いて、これをコピーしようとしています。
ところがEventInfo::GetRaiseMethodではnullが返ってきてしまいます。
ハンドラさえ取れれば以下と組み合わせて上手く行くと思うのですが。
https://msdn.microsoft.com/ja-jp/library/ms228976%28v=vs.110%29.aspx

状況:
なおC#だと以下で上手く行きます。
http://stackoverflow.com/questions/6055038/how-to-clone-control-event-handlers-at-run-time
ただしC++だと、GetField("events")がnullptrを返してくるので駄目です。
キーワードは色々試してみましたが、当たりませんでした。

前から困っている点で、とらいえずいちいち書いて対応していますが、
見ていて汚いので書き直したいと思っています。
気長に待っていますので、どなたか対策をご存じの方はレスよろしくお願いします。
0898デフォルトの名無しさん
垢版 |
2015/04/12(日) 03:07:38.87ID:UeaTPkyU
auto f = (Component::typeid)->GetField("events", BindingFlags::NonPublic | BindingFlags::Instance);
auto v = f->GetValue(checkBox1);
f->SetValue(checkBox2, v);

でふるまいが同一になるけど。
0899デフォルトの名無しさん
垢版 |
2015/04/12(日) 03:39:58.42ID:DBf5x0AF
>>898
お早い回答ありがとうございます。
こちらで確認した結果、確かに動きました。

(Component::typeid) のところを私は Component::GetType() にしていたのが敗因のようです。
見よう見まねでやっているため、実はここら辺のところがいまいち分かっていません。
お手数をおかけ致しました。また、ありがとうございました。
0900デフォルトの名無しさん
垢版 |
2015/04/12(日) 03:49:39.70ID:UeaTPkyU
Component::GetType() は Form の中でなら GetType() と同じ。
C++で親クラスのメソッド呼ぶときの文法よ。
0901デフォルトの名無しさん
垢版 |
2015/04/12(日) 10:00:53.76ID:DBf5x0AF
>>900
了解です。ありがとうございます。
FormがComponentを継承しているのを関知していませんでした。
0902897
垢版 |
2015/04/15(水) 19:57:16.10ID:F8+sQhgK
>>898
これ、少なくとも numericUpDown の ValueChanged イベントはコピーできないことが分かりました。
その他は不明です。
元々このやり方はどのドキュメントにも書いていないらしいので、文句は言えないのですが、
どなたか解決策をご存じであれば教えてください。

なお、Button の Click イベントについては、また別の解を見つけました。
似たようなものですが、keyが必要なようです。
http://stackoverflow.com/questions/293007/is-it-possible-to-steal-an-event-handler-from-one-control-and-give-it-to-anoth
ただ、Button Click 自体はこちらで試す限り、 >>898 でコピーできています。
0903デフォルトの名無しさん
垢版 |
2015/04/29(水) 20:01:07.13ID:3xtog1sc
マネージクラスのポインタを取得(pin_ptr)し、ネイティブクラスのポインタにキャストする方法を探しています。

class NativeClass
{
 int Hoge;
};

[StructLayout(LayoutKind::Sequential)]
public ref class ManagedClass
{
private:
 int mHoge;

public:
 property Int32 Hoge { Int32 get() { return this->mHoge; } }
};

mHogeがinternalの場合は下記でできますが、privateの場合はどう書けば良いのでしょうか?

ManagedClass^ managedClass = gcnew ManagedClass();
pin_ptr<int> pManagedClass = &managedClass->mHoge;
NativeClass* pNativeClass = (NativeClass*)pManagedClass;
0904デフォルトの名無しさん
垢版 |
2015/04/29(水) 23:24:10.23ID:wtD4uRPe
property const Int32% Hoge { const Int32% get() { return this->mHoge; } }
にすれば、&managedClass->Hoge が interior_ptr<const int> になるから後は適当にキャストすればいいんでは。
0905デフォルトの名無しさん
垢版 |
2015/04/30(木) 23:38:42.52ID:EZeUEJ9k
>>904
返信ありがとうございます。
トラッキング参照のプロパティはC#側で扱えなくなってしまうので避けたいです。
フィールドを参照しないと無理みたいなので、mHogeを公開するようにしようと思います。
ありがとうございました。
0906デフォルトの名無しさん
垢版 |
2015/05/01(金) 20:25:15.13ID:1uBqK3bl
知ってるかもだけど、ManagedClass が value class, value struct なら
pin_ptr<ManagedClass> を reinterpret_cast<NativeClass *> するのは安全だったはず…
0907デフォルトの名無しさん
垢版 |
2015/05/08(金) 23:36:54.66ID:V8hi9yRP
MessageBoxを親の中央に表示する簡単な方法はないですか?
自分でフォームを作ってしまえばいいんでしょうか?
最近までVC++6.0でMFCしか触ったことない自宅へぼプログラマです
0912デフォルトの名無しさん
垢版 |
2015/05/20(水) 23:36:56.86ID:DchNMAYq
休日プログラマです。

環境:Visual Studio 2012 express
SQLサーバ:SQL Server 2012 express

ODBCドライバを用いて、フォームから検索ワードを取得し、
C++/CLIでのプリペアドステートメントを発行して結果を取得したいのですが、
それを用いたlikeなど部分検索SQLの結果取得でハマったまま先に進めません。

SQLCHAR search[255];
std string sql = "select hoge, strhoge from hogetbl where strhoge like \%?\%";
SQLPrepare(hstmt,
(SQLTCHAR *) sql.c_str(),
,SQL_NTS);
SQLBindParameter(hstmt,1,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,sizeof(search),0,search,NULL);
SQLExecute(...

のように書いているのですが、プログラム上では何をやってもSQL_NO_DATAが返ります
あたりまえですがSQLそのものはServerのクエリで確認したところ通っています //?の所を'(任意文字列)'にした結果

また、SQL構文をLIKEの代わりにSQLのCHARINDEXを用い項目を増やして使ってみたのですが、同じようにダメでした。
// case when charindex(?,strhoge) > 0 then 1 else 0 end as searchflg ....
// where searchflg = 1 のように

ここには書き戻しできないのですが、escape句も試用したことがありますが、無理でした。
で、このLIKE以外は問題なく動きます。
また、他の機能はほとんどODBCで書いちゃったのでADOはやりたくないです。
何かいい方法ありませんでしょうか。よろしくお願いします。
0914912
垢版 |
2015/05/21(木) 00:02:48.74ID:6QiHBSDD
ああ、言い忘れていてすみません。
それもやりましたが、ダメでした
0916912
垢版 |
2015/05/22(金) 01:16:43.85ID:YmYYGDUM
うーん、それもやってみます。
あと、他の方はこうした事でハマったりは特にありませんでしたでしょうか。
書いてるのが一人でやってるのもあって、本当にプリペアドでの部分検索が可能かどうかが少し不安です
もちろん、突き詰めればなんでも可能なのでしょうけれども……
0918912
垢版 |
2015/05/29(金) 21:54:54.52ID:ky+HtZPS
912です。>>917さんの意見も含め、別の観点からもみてみたところ
・・・非常にお恥ずかしいオチになったのですが、解決しました。

問題はコードではなく、BindParameter時のCHAR検索する箇所(SQL_CHAR)が
DB側でいつの間にかvarcharになっていたのが原因でした。合わせてやると簡単に使えるように…
みなさん、お騒がせして申し訳ありません。
0919912
垢版 |
2015/05/29(金) 22:03:04.73ID:ky+HtZPS
>>918
×CHAR検索する箇所(SQL_CHAR)がDB側でいつの間にかvarcharになっていた
○CHAR検索(SQL_CHAR)としていたのに、対象のDB側の項目の型がvarcharになっていた
0920デフォルトの名無しさん
垢版 |
2015/09/15(火) 21:43:10.94ID:sv5Bl9TI
質問です。

上手いことsscanfを.NETで実装する方法ってありますか?
ポインタが上手く渡せず困っています。

なお、正式に習ったわけではなく、見よう見まねでやっているため、
単純なところで勘違いがあるかもしれませんが、その時も指摘して頂けたら助かります。
0921デフォルトの名無しさん
垢版 |
2015/09/15(火) 21:43:39.42ID:sv5Bl9TI
【これまでの経緯】
プログラムが間延びしてきたため、
これまで個別にちまちま書いていたファイル読み出し部分をsscanfで纏めて整理しようとしています。
ググッたところ、.NETにはsscanfそのものはなく、どうやら皆さん苦労しているようでした。
http://stackoverflow.com/questions/4223917/c-sharp-equivalent-of-c-sscanf
http://stackoverflow.com/questions/492262/is-there-an-equivalent-to-sscanf-in-net
http://www.blackbeltcoder.com/Articles/strings/a-sscanf-replacement-for-net
ただ自分の場合はcsvの読み出しで順番と対象だけ指定できればいいので、
以下のように組んでみました。(ただしまだ動かしていないので動かないかもしれません)

private: int sscanf_csv(String^ str, String^ format, array<void**>^ pointers){
array<String^>^ strs = str->Split(',');
array<String^>^ fmts = format->Split(',');
int i=0;
while (i<strs->Length && i<fmts->Length) {
if (fmts[i]=="int") {
if (!Int32::TryParse(strs[i],(int%)pointers[i])) break;
} else if (fmts[i]=="double") {
if (!Double::TryParse(strs[i],(double%)pointers[i])) break;
} else if (fmts[i]=="float") {
if (!Single::TryParse(strs[i],(float%)pointers[i])) break;
} else if (fmts[i]=="string") {
*(interior_ptr<String^>)pointers[i] = strs[i];
}
i++;
}
return i;
}

Stringのところは怪しいですが、intとdoubleとfloatはネイティブなら問題ないと思っています。
0922デフォルトの名無しさん
垢版 |
2015/09/15(火) 21:44:06.10ID:sv5Bl9TI
【問題点】
・マネージドのクラスではメンバにネイティブ配列が使えないため、
書き込み対象にどうしてもマネージド配列の要素を指定することが必要となりますが、
interior_ptrをvoid**にキャストできません。
仕様上、interior_ptr → pin_ptr → int → void** にはキャストできる(っぽい)のですが、
 ・interior_ptrは配列に出来ない(array<interior_ptr<int>> も interior_ptr<int> hoge[] もエラー)
 ・pin_ptrも同様に配列に出来ない。さらにローカル変数として宣言しないと駄目っぽい。
ため、これらを回避するためにはベタにコードする必要があり、余計に見にくくなります。
・そもそも void** にしているのは可変長引数がいまいちだったからなのですが、
上記のように interior_ptr が配列に取れないから多分可変長も無理です。
・自分の場合は1行につきせいぜい10個程度の代入なので最悪べた書きでラップしてもいいのですが、
interior_ptr<Type>は型指定があり、型の順番は変更したいのでこれも厳しいです。

【出来ればいいなと思っている記述】
array<int> ary_int = gcnew array<int>(10);
array<double> ary_double = gcnew array<double>(10);
sscanf_csv(line0, "int,double", gcnew array<void**>(2){&ary_int[0], &ary_double[0]});
sscanf_csv(line1, "double,int", gcnew array<void**>(2){&ary_double[1], &ary_int[1]});

という感じです。良い案があればお願い致します。
0923デフォルトの名無しさん
垢版 |
2015/09/16(水) 11:35:11.25ID:L4xvtXb4
>922
ttps://gist.github.com/anonymous/db1149cb0a1afbd1f6d8

書いてて思ったけど、変に凝るよりも↓みたいな奴の方が読む人にやさしい…
auto x = gcnew CSV(line1);
ary_int[0] = x->read_int(0);
ary_double[0] = x->read_double(1);
0924デフォルトの名無しさん
垢版 |
2015/09/16(水) 21:00:32.05ID:sRYuFuHf
>>923
おお、ありがとうございます。
template<typename ... Ts>でTsはバラバラでもいけるんですね。知りませんでした。
あと、再帰で一つずつ剥がすのも思いついていませんでした。ググルと定番のようですがorz

> 書いてて思ったけど、変に凝るよりも↓みたいな奴の方が読む人にやさしい…
ちなみにその記述は今の状態です。
ただ、これだと抽象度が低いため記述量が増え、ちょっと保守性に問題を生じ始めています。
結局のところ、同じフォーマットの行を大量に処理して配列に突っ込むだけなので、
最終的には「ファイル名」「フォーマット」「対象配列」でよく、最上位からは(型情報ありなら)

parse_csv(filename, &ary0, &ary1, ...);

の1行にしたいのです。その下のファイル→行のところでコメント等をはがし、
delegateでparse_lineを呼ぶ算段でしたが、ポインタが渡せずに困っていました。
大変助かりました。ありがとうございました。


と思ったのですが、parameter pack はC++11の機能で、VS2013以降からのようです、、、
VS2015でそちらのコードが動作するのを確認しました。
自分が使っているのはVC++2008なので、この機会に移行を考えますorz
当面はせいぜい10個なのでunpackしたものを自分で書きますが、、、
0925デフォルトの名無しさん
垢版 |
2015/09/16(水) 21:06:19.21ID:sRYuFuHf
すいません、やや話が前後しているので念のため一部訂正します。

元々 delegate から parse_line を呼ぶつもりでしたが、
最終的には可能なら parse_csv に纏めようとしています。
ただ parameter pack が使えないとやっぱキツいですね、、、
0926デフォルトの名無しさん
垢版 |
2015/09/16(水) 22:14:50.26ID:L4xvtXb4
行によってフォーマットが違わない(ファイルによっては違うのかな)のなら、
行をパースした結果の型を定義しちゃったほうが保守性は上がると思うけど、縦方向の配列が必要なんだろうなぁ。
0927デフォルトの名無しさん
垢版 |
2015/09/16(水) 22:41:51.71ID:sRYuFuHf
>>926
はい、ファイルによってフォーマットは違い、行では変わりません。
演算ソースを読み込むのに使うので、速度は遅くても構いません。

ただ一部、各行の先頭数値によって行のフォーマットを変えている部分があるため、
元々はメンバ関数内で parse_file を呼び、フォーマット毎の parse_line を delegate で渡すつもりでした。
ただこれはソースファイルが増えるのが面倒なので一部にパッチを当てたからであり、
きちんと修正すれば parse_file に一本化できるので、この方向で検討中です。

実は縦方向の配列は不要で、各行での構造体化も検討中です。
0928デフォルトの名無しさん
垢版 |
2015/09/16(水) 22:55:17.14ID:sRYuFuHf
すいません、また細かいところで間違えました。一応念のため訂正しておきます。

× 元々はメンバ関数内で parse_file を呼び、フォーマット毎の parse_line を delegate で渡すつもりでした。
○ 元々は上位で parse_file を呼び、対象オブジェクトのメンバ関数を delegate で渡し、
 メンバ関数内で先頭数値を見てフォーマットを区別し、そこから parse_line を呼ぶつもりでした。(現時点で動作中)

今は上位で メンバ関数 Hoge.init(filename) を呼び、init内で全部済ませる方向です。

これまで全くオブジェクト指向をしておらず、それでも大して問題なかったのですが、
いい加減無理になってきたので、今更ながら粗結合化をやろうかというところです。
0929デフォルトの名無しさん
垢版 |
2016/02/15(月) 00:11:59.92ID:BuMWAFI4
「System.Collections.Generic.List<T>型」を「LPARAM型」に変換する方法、
またその逆の変換をする方法、を教えて下さい。

List<T>型をLPARAM型に変換する必要があり、
その後で、List<T>型をLPARAM型から再取得する必要があるのです。
0930デフォルトの名無しさん
垢版 |
2016/02/15(月) 01:15:53.23ID:Rn1JhND3
「その後で」がスコープを抜けた後を意味するなら、そのような方法はありません。
0931デフォルトの名無しさん
垢版 |
2016/02/15(月) 07:40:32.53ID:7IG9/wk9
marshal_as を実装すればいいと思うよ。
LPARAM って実体は void** じゃなかったっけ
0932デフォルトの名無しさん
垢版 |
2016/02/16(火) 07:41:35.26ID:uJkK1HCP
>>931
言語はC++ cli です。

msclr::interop::marshal_context mct;
LPARAM lParam = mct.marshal_as<LPARAM>(this->child_window_list);
↑で実装すると↓のコンパイルエラーとなります。
error C4996: 'msclr::interop::error_reporting_helper
<_To_Type,_From_Type>::marshal_as':
This conversion is not supported by the library or the header file needed for this conversion is not included. Please refer to the documentation on 'How to: Extend the Marshaling Library' for adding your own marshaling method.

またList<T>型をLPARAM型に再変換する方法が分かりません。
0934デフォルトの名無しさん
垢版 |
2016/02/16(火) 15:12:48.61ID:l0bB/6+q
LPARAMの使い道がEnumWindowsの第二引数とかだったらやりようがあるけど、そういうコードではない?
0935デフォルトの名無しさん
垢版 |
2016/02/17(水) 07:42:51.53ID:6vFi9dMa
解決しました。
c++の世界で一時変数を設けて、ポインタを渡し、reinterpret_castで復元する、という方法です。
0937デフォルトの名無しさん
垢版 |
2016/02/20(土) 19:06:01.50ID:HOPxSzsv
質問です。
+= で追加したフォームのイベント順を入れ替えたいのですが、やり方はありますか?

条件
1. デザイナは使いたい(既に大量に使っている)
2. 格好悪い書き方で全く問題ないが、全体的に書き直すのはNG

状況
numericUpDown->Changed 等に対してデザイナ上から再描画関数を割り当てています。(A)
(波形を表示する時のボリュームのような使い方です)
デザイナではフォームはデフォでは static でないため、
内部の別クラスからは numericUpDown->Value 等にはアクセスできません。
(自分でstaticと書いてコンパイルを通すことは出来ますが、デザイナで変更するたびに戻されます)
そこでイベントに別関数も割り当て、そこで内部 static struct に Value 等を書かせ、(B)
別クラスからはこの static struct を参照しています。

このとき、AとBの経路が完全に分離しているうちはよかったのですが、
統合していくうちにA内部から別クラスを呼ぶことが発生し、 static struct が未更新なのでバグっています。
イベントは追加順に呼ばれるようです。
デザイナで指定したイベント関数はフォーム生成時に指定される為、必ず A->B の順で呼ばれることになります。
これを B->A の順に入れ替えたいのですが、方法はありますか?
0938デフォルトの名無しさん
垢版 |
2016/02/20(土) 19:06:30.87ID:HOPxSzsv
プログラムイメージ
Form^ someForm; // デザイナで作成したため、static ではない
someForm->Changed += 再描画関数; // (A)
someForm->Changed += struct更新関数; // (B)

static ref struct FormData {
Decimal someForm_value;
} formData;

function struct更新関数(){ // (B)
formDataを更新
}
function 再描画関数(){ // (A)
formDataを使う別クラスを使用 // formDataは未更新なのでバグる
}

やってみたこと
numericUpDown->Changed = Delegate::Combine(struct更新関数, 再描画関数); // 上書き再設定しようとしたが = は使えない
どうやら +=(add) と -=(remove) しかないので、(中身を参照できない)
一つずつ array<Delegate^> に吸い出して += で希望順にちまちま再設定も出来そうにありません。
全部の(A)の頭に(B)を追加してイベント経路を一本化すればいいのは分かりますが、
これは大量に書き換えが必要となります。
今現在(B)は後付で全てのフォームを列挙して追加しています。
この部分だけの変更に留められるのならそうしたいのです。
リフレクションも試しましたが、以下でeventInfoは取れますがその先に進めません。
System::Reflection::EventInfo^ eventInfo = (NumericUpDown::typeid)->GetEvent("ValueChanged");

以上、よろしくお願い致します。
0939デフォルトの名無しさん
垢版 |
2016/02/21(日) 05:32:00.14ID:SNLM1Bng
> デザイナではフォームはデフォでは static でないため、
> 内部の別クラスからは numericUpDown->Value 等にはアクセスできません。

ここで結果と原因の理解が食い違ってるので設計が悪くなってるのでは。

FormDataはstaticにせずForm1のメンバにして、その中身が変化したときのイベント
(ここに再描画関数を += して、EventArgsでパラメータを渡す)を足すのが良いのでは。
0940デフォルトの名無しさん
垢版 |
2016/02/21(日) 12:45:43.68ID:Ur7lNYiz
>>939
回答ありがとうございます。

それでも解決しますが、それは全面改訂になります。
既に(B)を全ての(A)の頭に入れるという解決策はあり、それの方がデグレードの危険が少ないです。
ただ、リフレクション等で(B)と(A)の順を入れ替えられると、数行の変更で済み、デグレードは発生しません。
だからそれを探しています。

Form1と別クラスCを追加して再度説明します。
全てはForm1の内部クラスです。継承はしていません。
0941デフォルトの名無しさん
垢版 |
2016/02/21(日) 12:46:15.32ID:Ur7lNYiz
【今】
ref class Form1{
Form^ someForm; // デザイナで作成したため、static ではない
someForm->Changed += 再描画関数; // (A)
someForm->Changed += struct更新関数; // (B)

static ref struct FormData {
Decimal someForm_value;
} formData;

function struct更新関数(){ // (B)
formDataを更新
}
function 再描画関数(){ // (A)
// struct更新関数() // (B)を += せずにここに入れれば解決する、ただし変更箇所多数
formDataを使う別クラスCを使用 // formDataは未更新なのでバグる
}
ref class 他のクラスC {
描画用データ作成 // ここで someForm->Value を使いたいが直接には出来ないので仕方なく static formData を確認
}
};

問題点:
クラスCから someForm->Value が取れないので static struct FormData で誤魔化す。
ただしこれだとイベント順が「描画(A)」→「データ更新(B)」となり、描画内容が1イベント分ずれる。
このため、(B)と(A)の処理順を入れ替えたいが、方法が見あたらない。
0942デフォルトの名無しさん
垢版 |
2016/02/21(日) 12:46:44.50ID:Ur7lNYiz
>>939の提案】
ref class Form1{
Form^ someForm; // デザイナで作成したため、static ではない
someForm->Changed += struct更新関数; // (B)

ref struct FormData { // static ではない
Decimal someForm_value;
} formData;
formData->someForm_value->Changed += 再描画関数; // (A) // 自作クラスFormDataにChangedイベント追加

function struct更新関数(){ // (B)
formDataを更新
}
function 再描画関数(){ // (A)
formDataを使う別クラスCを使用 // formDataは常に更新済み、formDataを呼び出し時に渡す
}
ref class 他のクラスC {
描画用データ作成 // formData を参照
}
};

問題点:
イベント処理順は「データ更新」→「描画」と正しく固定される。
ただし全面改訂になる。
0943デフォルトの名無しさん
垢版 |
2016/02/21(日) 12:47:27.88ID:Ur7lNYiz
> ここで結果と原因の理解が食い違ってるので設計が悪くなってるのでは。
結果: 描画に使われるデータが1イベント分ずれる
原因: イベント順が「描画」→「データ更新」だから
何か間違いはありますか?

データ構造としては本来は class Form1 : FormData となるべきため、
static で使うことも問題ないと思います。
既に記述されて動いているプログラムがあり、それを変更しようとしています。
データ更新→描画にプログラム上で固定するのはスクラッチからなら当然ですが、その場合にも結局
「どのデータが更新されたか→どの部分を再描画する必要があるか」を記述する必要があります。
この部分は今既にデザイナ上にあり、動いているので、それをそのまま利用する方法を探しています。
0945デフォルトの名無しさん
垢版 |
2016/02/22(月) 00:23:23.86ID:GxEKSJ9o
リンク先のコードでイベント順を入れ替えることが出来ました。
ありがとうございました。

プログラム構造については色々意見はあるとは思いますが、
最初から固まっている仕様に対して一度作って終わりなら誰も苦労しませんよ。
複数有る解決策のうち、今現在見える範囲での最適解をその都度選んでいくしかありません。

A. イベント順を入れ替えても
B. 各イベントハンドラの頭にデータ更新を挿入しても
C. 他クラスに対していちいちForm1オブジェクトを渡してstaticではなくしても

制御フローは同じです。(切り出し面が異なるだけ)
今後FormDataクラスや「他のクラスC」はForm1外でも使う可能性があるのと、
デグレードに対するデバッグの困難さを考えて、今回はAを選んでいるだけです。

まあいずれにしても、解決しました。
ありがとうございました。

なおリンク先、最後に小言が書いてありますが、完全に同意ですよ。
本来はイベントテーブルを参照できるメソッドが有ればいいだけです。
0946デフォルトの名無しさん
垢版 |
2016/02/23(火) 04:03:35.79ID:zeSeypn1
本来はまともな設計をすればいいだけだよ
+= した順番に呼ばれるのもたまたまそういう実装になってるだけでしょ
0948デフォルトの名無しさん
垢版 |
2016/04/25(月) 16:38:42.40ID:FkG7uZgr
質問失礼します。

'abc.exe': 'C:\Visual Studio 2008\Projects\xyz.dll' を読み込みました。Cannot find or open the PDB file
'abc.exe': 'C:\Visual Studio 2008\Projects\xyz.dll' をアンロード

このアンロードはどうやって止めるのでしょうか?

実行した際に、dll内のメソッドを参照できないようで、以下のエラーとなります。
ハンドルされていない例外: System.IO.FileNotFoundException: ファイルまたはアセン
ブリ 'hoge.dll'、またはその依存関係の 1 つが読み込めませんでした。
指定されたモジュールが見つかりません。
場所 hoge.hogeclass..ctor()
場所 main(Int32 argc, SByte** argv)
場所 _mainCRTStartup()
コンパイルはできています。

よろしくお願いします。

(なんか急にできなくなった気がします。前は、問題無だったはずなのになぁ)

追記

他にも、以下のような、謎のメッセージも出ています。

'abc.exe': 'ImageAtBase0x10000000' を読み込みました。含める/除外する設定により、読み込みは無効になっています。
'abc.exe': 'ImageAtBase0x10000000' をアンロード

よろしくおねがいします。
0951948
垢版 |
2016/04/27(水) 15:26:32.30ID:pZs1yVgK
思い出しました。

ildasm,ilasmをつかって、その該当のdllのPCBを作りました。
(dllの中まで、デバッガで追いかけるためです)
あたらしくコンパイルしたDLLへ、前のPCBがなかったものから、リンクを張り替えました。

そしたらエラーが出るようになった気がします。
(あくまで、気がするだけです。なんら、確かな関連はわかりません)

しかし、現在は、以前のオリジナルのDLLをリンクしています。
その状態でエラーが出ています。

>>950
回答ありがとうございます。

/LIBPATH の場所
exeと同じフォルダ
program filesフォルダのvisualSTUDIOフォルダ

それらに置き直しました。が、駄目でした。
レス数が950を超えています。1000を超えると書き込みができなくなります。

ニューススポーツなんでも実況