こんにちは高木です。たまには愚痴を吐いてみようと思います。そういうのが嫌な方はこの時点でそっと立ち去ってください。
現在私が関わっている開発ではC++/CLIを使っています。このC++/CLIがなかなかの曲者で、いつになっても使いこなせません。結構長いことやっているんですけどねえ。
「今どきC++/CLIなんか……」と笑われるかもしれません。けれども、マネージドコードとアンマネージドコードの橋渡しをするにはやはりC++/CLIが必要です。簡単な引数や返却値の受け渡ししかしないのであれば、DllImportを使ってC#からアンマネージドコードを直接呼び出すのもありなんですが、複雑なデータ構造を受け渡すにはC++/CLI以外の選択肢がないんですよ。
C++/CLIのどういうところが辛いかというと……
もともとC++/CLIは標準C++の上位互換だという触れ込みだったと思うんです。ところがそこでいう標準C++はおそらくC++98ですよね。いや、実際にはC++98に対しても上位互換なんかではなかったんです。たとえば次のようなコードがあったとします。
0 1 2 |
const char* s = "hello" + 2; |
とくにこれといった問題はないと思うんですよ。sには最初の’l’(エル)へのポインタが格納されるはずですよね。ところがC++/CLIではこれはコンパイルエラーになるんです。えっ、標準C++の上位互換なんですよね?
どうやら、”hello” + 2とした時点で”hello2″という文字列を表すSystem::String^型になってしまうようなんです。それをconst char*型に格納しようとしてもエラーになるということだそうです。どういうわけか、次の書き方ならOKのようです。
0 1 2 |
const char* s = &"hello"[2]; |
何はともあれ、回避手段があるのはいいことです。
一番難儀するのはマネージドクラスの場合です。普通のC++のクラスならできることがマネージドクラスではできないんですよ。たとえば、const修飾子付きのメンバ関数を定義できないんですよね。これは普通のC++とは設計の仕方が根幹から変わってきますよね。とはいえ、const修飾についてはC#でもできないので、.NETはそういうもんなんでしょう。
省略時実引数(デフォルト引数)ならC#でも使えるので(もちろん標準C++でもOK)、これならマネージドクラスでも使えるだろうと思ったら、コンパイルエラーになるんです。一体どうしろと!
C++/CLIを使っていて一番辛いのは、マネージドクラスのメンバ関数の中ではラムダ式を定義できないことです。C++98にはラムダ式がなかったから仕方がないんですかね。でも、C#ならローカル関数もラムダ式も使えるじゃないですか。たしかにC#のローカル関数やラムダ式とC++のそれは微妙に異なりますが、そこをなんとかするのがコンパイラの仕事だと思うんですよ。
ほかにも挙げるときりがないんですが、今日のところはこれぐらいにしておきます。これからもときどき愚痴を吐くので、よかったら聞いてください。