LoginSignup
1
0

More than 1 year has passed since last update.

C# から C ソースの生成・コンパイル・実行まで

Last updated at Posted at 2022-03-11

環境

Ubuntu 18.04 (WSL2 / Windows 11)
.NET 5.0 / C# 9.0
gcc 7.5.0

やること

ワークスペース直下にCソースを生成し、gccでコンパイルして実行まで.NETアプリ(C#)で行います。gccが吐いたエラーはそのまま表示します。

ソース生成

Program.cs
// using System.Text;
// using System.IO;

var sb = new StringBuilder();
sb.AppendLine($@"#include <stdio.h>");
sb.AppendLine($@"");
sb.AppendLine($@"int main() {{");
sb.AppendLine($@"    printf(""Hello C!\n"");");
sb.AppendLine($@"    return 0;");
sb.AppendLine($@"}}");

var writer = new StreamWriter("hello.c");
writer.WriteLine(sb.ToString());
writer.Close();     

これで、↓が生成されます。

hello.c
#include <stdio.h>

int main() {
    printf("Hello C!\n");
    return 0;
}

ちょっと例が悪いですが、ソースには変数の埋め込みとかしたいはずなので $@""形式の補完文字列を使っています。この文字列には、{a}{a * b}のような形で(ほとんど)任意の変数や式を書くことができ、また改行文字などをエスケープできます(かわりに、文字として出力させたい場合は"のほか{}も2つ重ねて書く必要があります)。ちなみに$@から始まる補完文字列は複数行をまとめて書けるので、たとえば

C#
string source = $@"
#include <stdio.h>

int main() {{
    printf(""Hello C!\n"");
    return 0;
}}
";

みたいにすることもできます。ただ、ソース文字列の左にあるインデントが出力先にそのまま反映される(エディタ・フォーマッタの設定次第?)ので、たとえば同じ方法でCではなくPythonのソースファイルを生成すると怒られる可能性があります。ソース部分がインデントされていなければ問題ないはず。

コンパイル・実行

Program.cs
// using System.Diagnostics;

var pInfo = new ProcessStartInfo()
{
    FileName = "gcc",
    Arguments = "hello.c",
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true
};

var process = Process.Start(pInfo);
process.WaitForExit();
var output = process.StandardOutput.ReadToEnd();
Console.WriteLine(output);
var error = process.StandardError.ReadToEnd();
Console.WriteLine(error);

UseShellExecutefalse にしておかないと、C#側で出力を読めません。逆に言えば、C#側で読みだす必要がなければUseShellExecutetrueにしておくことで標準出力をシェルにそのまま吐き出してくれます(その場合はRedirectStandardOutputfalseにしておかないと例外)。ここではコンパイルの成否によってそのまま実行するかいったん止めるか分けたかったのでこうなっています。

2022/03/20追記
...
標準エラーもリダイレクトしないとコンパイルの成否判定はできません(ソース修正済み、RedirectStandardError = trueとすればOK)。
当たり前ですがすっかり失念していました...
...

Arguments には空白区切りにして複数の引数を記述できます。たとえば、

Arguments = "hello.c -o hello"

などとすることもできます。gccなら-march-OオプションなどもOK。

同じ要領で、FileNamea.out(または-oオプションで指定した実行ファイル名)にしてやればコンパイルしたCアプリを実行できます。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0