-
Notifications
You must be signed in to change notification settings - Fork 692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature request] Bindings to Roslyn csc.dll or example in docs of using Roslyn to compile a C# file or a code snippet in a string #2196
Comments
This is out of scope for Python.NET. |
An example in docs would be nice though even if you consider this not needed to add in the codebase :) For instance, as you can see in https://gist.github.com/vadimkantorov/c9ab97aff995ea01ea7f6248ddc733bc#file-csharpfrompython-sh the path discovery is a beast: DOTNETSDKVER=$("$DOTNET_ROOT/dotnet" --version)
DOTNETFWKVER=$("$DOTNET_ROOT/dotnet" --list-runtimes | grep Microsoft.NETCore.App | tail -n 1 | cut -d' ' -f2)
DOTNETLIBDIR="$DOTNET_ROOT/shared/Microsoft.NETCore.App/$DOTNETFWKVER"
"$DOTNET_ROOT/dotnet" "$DOTNET_ROOT/sdk/$DOTNETSDKVER/Roslyn/bincore/csc.dll" $(find "$DOTNETLIBDIR" -name "*.dll" -printf '-r:"%p" ') -target:library -out:csharpfrompython.dll csharpfrompython.cs If these paths are available somewhere under the Here is a complete snippet: output_path = os.path.abspath('foo.dll')
input_path = os.path.abspath('foo.cs')
os.environ['PYTHONNET_RUNTIME'] = 'coreclr'
os.environ['DOTNET_ROOT'] = os.path.expanduser('~/.dotnet')
import clr
DOTNETSDKVER=subprocess.check_output([os.path.join(os.environ['DOTNET_ROOT'], 'dotnet'), '--version']).decode().strip()
DOTNETFWKVER=[line.split()[1] for line in subprocess.check_output([os.path.join(os.environ['DOTNET_ROOT'], 'dotnet'), '--list-runtimes']).decode().splitlines() if 'Microsoft.NETCore.App' in line][-1].strip()
DOTNETLIBDIR=os.path.join(os.environ['DOTNET_ROOT'], 'shared', 'Microsoft.NETCore.App', DOTNETFWKVER)
csc_args_reference_assembly_paths = ['-r:' + os.path.join(dirname, basename) for dirname, dirs, basenames in os.walk(DOTNETLIBDIR) for basename in basenames if basename.endswith('.dll')]
csc_args_main = ['-target:library', '-out:' + output_path, input_path]
clr.AddReference(os.path.join(os.environ['DOTNET_ROOT'], 'sdk', DOTNETSDKVER, 'Roslyn', 'bincore', 'csc.dll'))
import Microsoft.CodeAnalysis.CSharp.CommandLine
Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Main(csc_args_reference_assembly_paths + csc_args_main)
clr.AddReference(output_path) Somewhat related on complete pipeline of using Roslyn + Assembly.Load: https://weblog.west-wind.com/posts/2022/Jun/07/Runtime-CSharp-Code-Compilation-Revisited-for-Roslyn - might be useful for other people looking to do this. |
For .NET Core embedding into Python, it is useful in educational/hack scenarios to allow the user to allow the user to not compile the C# code beforehand. E.g. a solution would be a Python binding (or docs example) to Roslyn/csc.dll of calling it from python to compile a C# code file or code snippet (without saving it to a file). An alternative would be binding to CSharpScript technology of Roslyn.
Originally discussed at #2195
In my example there https://gist.github.com/vadimkantorov/c9ab97aff995ea01ea7f6248ddc733bc I first prepare the compilation string, then compile the csharp code in
csharpfrompython.sh
, and only then call clr.AddReference in the python code. It would be great to call the compiler directly from the python code and have nice bindings to even maybe not store the assembly on disk and add it to clr.AddReference directly.Maybe the API could be
clr.CompileAndAddAssembly(code files, code snippets, compiler options, reference assemblies and other csc options)
or sth similarThe text was updated successfully, but these errors were encountered: