2

一部の C# コードを C++/CLI に変換するよう依頼されました。私のマネージャーの 1 人が、2 つの間の翻訳の概念に関する潜在的な落とし穴について尋ねました。

私は、両方の言語が共通インターフェイス言語にコンパイルされ、同じ共通言語ランタイムで実行されることをよく知っています。ただし、.NET Framework 4.5 用にコンパイルされ、File.Exists(someFile); を呼び出す C# コードの一部を保証できますか。.NET Framework 4.5 用にコンパイルされ、File::Exists(someFile) を呼び出す C++/CLI コードの一部とまったく同じ方法で、CIL にコンパイルされます。?

理論的には、答えはイエスです。これが .NET フレームワークの目的であると思われるからです。しかし、これを検証する方法はありますか?そうでなければならない/できないという技術的な理由はありますか?

4

2 に答える 2

3

There certainly are some pitfalls when you write C++/CLI code and you know C# well but not C++/CLI. I'll avoid turning this into a list question and enumerate all of them, just the more common mistakes:

  • C++/CLI requires you to be specific in the language syntax about the difference between value types and reference types. You have to use the hat^ on reference type references. Like String^ foo;. But sometimes you don't, you intentionally omit it. Like StreamReader file;. Which enables "stack semantics", an emulation of the C++ RAII pattern. Or in other words, the compiler will automatically dispose the file variable when it goes out of scope. You know this from the C# using statement. The biggest trap is using the hat when you should not, like int^ x = 42;. Which the compiler will accept without a complaint, but you end up with a boxed int which is extremely inefficient at runtime.

  • Development on the C++/CLI language and toolset stopped in 2005 and has been in maintenance mode since. It thus didn't acquire the goodies that C# got in that time frame, Linq certainly being the most significant addition. No lambda expression support, no anonymous types, no extension methods. You will not enjoy converting C# code that uses these syntax constructs.

  • There is only ever one reason to consider converting C# to C++/CLI, it is to take advantage of its great support for interop with unmanaged code. No need to wrangle pinvoke. A very common mistake is to compile everything to MSIL, including the native C++ code. Which works too well, the C++/CLI compiler is capable of compiling any C++ to IL as long as it is standard C++03 compliant code. But the result is inefficient, it certainly doesn't run as managed code at runtime and is jitted like normal but without the goodies from the native code generator. Which can do a better job optimizing code.

  • The output of the compiler is plain MSIL, the exact same kind that C# generates. Plus native code for the parts of your program where you use C++, producing a mixed-mode assembly. This gives the assembly a dependency on the bitness of the process. Or in other words, the AnyCPU target you might know from C# projects does not apply. This is something you need to be aware of in your EXE project, you must be explicit about the Platform target setting. With "x86" the common choice to ensure that your program will still work when it runs on a 64-bit operating system. If you want to run your program as a 64-bit process on a 64-bit OS then you'll need to create two builds of your C++/CLI assembly and deploy the correct one with your installer.

You have nothing to fear from a File::Exists(somefile) call, there's only one way to call that method in MSIL. The C++/CLI compiler will generate the exact same IL as the C# compiler. If you are really concerned about it then create confidence by looking at the IL with a decompiler like ildasm.exe

于 2013-07-22T10:57:10.123 に答える
1

[C] .NET Framework 4.5 用にコンパイルされた C# コードの一部と呼び出しが、.NET Framework 用にコンパイルされたC++/CLI コードの一部とまったく同じ方法File.Exists(someFile);で CIL にコンパイルされることを 1 つ保証します。 4.5 とコール?File::Exists(someFile);

いいえ、これは保証されません。

実際、C# コンパイラを介して同じソース コードを 2 回実行しても、同じバイナリ出力が生成されるとは限りません。したがって、2 つの異なる言語用の 2 つの異なるコンパイラが異なるコードを生成する可能性があることは確かです。

(気をつけてください、そうなるかもしれませんし、実際にはそうなることが多いでしょう。しかし、ここでは保証について話しているのです。)

私が理解できないのは、なぜこれが問題になるのかということです。もちろん、同じメソッドを呼び出しているため、コードは同じことを行います。これはドキュメントによって保証されているだけでなく、.NET Framework DLL を逆アセンブルすることで自己検証可能です。

2 つのプログラムのバイナリが同一であるとは限りません。とにかく、JIT コンパイラーを通過すると、何も起こらないというわけではありません。それが要点です。

于 2013-07-22T08:58:54.007 に答える