Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

azurefx/DotNET.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

39 Commits

Repository files navigation

DotNET.jl

Build Status PRs Welcome

This package provides interoperability between Julia and Common Language Runtime, the execution engine of .NET applications. Many languages run on CLR, including C#, Visual Basic .NET and PowerShell.

Prerequisites

  • Julia version 1.3+
  • .NET Core Runtime version 2.2+ (Download)

WinForms and other GUI-related features require a desktop runtime.

If the package fails to locate the runtime, set DOTNET_ROOT environment variable to the path containing the dotnet or dotnet.exe binary.

.NET Framework is not supported yet.

Installation

In the REPL, type ]add DotNET and press Enter.

(v1.x) pkg> add DotNET

Or use Pkg.add for more options:

julia> using Pkg
julia> Pkg.add(PackageSpec(url = "https://github.com/azurefx/DotNET.jl"))

Usage

julia> using DotNET

Types and Objects

DotNET.jl provides the T"AssemblyQualifiedTypeName" literal for type reference:

julia> Console = T"System.Console, mscorlib"
System.Console

Given a type object, you can access its properties or methods using the dot operator:

julia> Console.WriteLine("Hello from .NET!");
Hello from .NET!

To create an object, use the new syntax:

julia> T"System.Guid".new("CA761232-ED42-11CE-BACD-00AA0057B223")
System.Guid("ca761232-ed42-11ce-bacd-00aa0057b223")

All .NET objects are represented by CLRObjects in Julia, including types:

julia> typeof(Console)
CLRObject
julia> typeof(null)
CLRObject

null is a built-in object that does not refer to a valid .NET object. When you try to access a member on a null value, a System.NullReferenceException is thrown.

Arguments passed to .NET methods are automatically converted to CLRObjects, and return values are converted to corresponding Julia types:

julia> T"System.Convert".ToInt64("42")
42

Or you could do some explicit conversions:

julia> s = convert(CLRObject, "")
System.String("")
julia> DotNET.unbox(s)
""

To pass an argument by reference (out/ref in C#), wrap it into a Ref object:

julia> result = Ref{Int}()
Base.RefValue{Int64}(212700848)
julia> T"System.Int64".TryParse("1970", result)
true
julia> result[]
1970
julia> result = Ref(null)
Base.RefValue{CLRObject}(null)
julia> T"System.Int64".TryParse("2022", result)
true
julia> result[]
System.Int64(2022)

Arrays and Collections

To copy a multidimensional array from .NET to Julia, use collect method:

×ばつ2 Array{Int64, 3}: [:, :, 1] = 1 3 2 4 [:, :, 2] = 5 7 6 8">
julia> arr = convert(CLRObject, reshape(1:8, 2, 2, 2))
System.Int64[,,]("System.Int64[,,]")
julia> collect(arr)
2×ばつ2×ばつ2 Array{Int64, 3}:
[:, :, 1] =
 1 3
 2 4
[:, :, 2] =
 5 7
 6 8

CLI Array elements are stored in row-major order, thus the equivalent definition in C# is

public static long[,,] Get3DArray() {
 return new long[2, 2, 2] {
 {{1, 2}, {3, 4}},
 {{5, 6}, {7, 8}}
 };
}

To index into arrays, use arraystore and arrayload methods. Note that CLI Arrays use zero-based indexing.

julia> DotNET.arraystore(arr, (1, 1, 1), 0)
null
julia> DotNET.arrayload(arr, (1, 1, 1)) == collect(arr)[2, 2, 2]
true

If an object implements IEnumerable interface, you can call GetEnumerator to iterate over the array:

julia> ch = Channel() do it
 e = arr.GetEnumerator()
 while e.MoveNext()
 put!(it, e.Current)
 end
 end
Channel{Any}(0) (1 item available)
julia> collect(ch)
8-element Vector{Any}:
 1
 
 8

Or just use the for-in loop:

for x in arr
 println(x)
end

Loading External Assemblies

If you have a DLL file, you can load it using reflection:

julia> T"System.Reflection.Assembly".LoadFrom(raw"C:\Users\Azure\Desktop\test.dll")
System.Reflection.RuntimeAssembly("test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")

Now you have access to types defined in the assembly.

Generics

Generic types are be expressed in the following ways:

julia> ListT = T"System.Collections.Generic.List`1"
System.Collections.Generic.List`1[T]

julia> ListInt64 = T"System.Collections.Generic.List`1[System.Int64]"
System.Collections.Generic.List`1[System.Int64]

The number 1 after the backtick indicates the type System.Collections.Generic.List<T> has one type parameter. ListT has a free type variable, just like Vector{T} where T in Julia. A type that includes at least one type argument is called a constructed type. ListInt64 is a constructed type.

One can substitute type variables and make a constructed type by calling makegenerictype method:

julia> DotNET.makegenerictype(ListT, T"System.String")
System.Collections.Generic.List`1[System.String]

To invoke a generic method, put type arguments into square brackets:

julia> list = ListT.new[T"System.Int64"]()
System.Collections.Generic.List`1[System.Int64]("System.Collections.Generic.List`1[System.Int64]")

Delegates

To create a delegate from a Julia method, use delegate method:

julia> list = ListT.new[T"System.Int64"](1:5)
System.Collections.Generic.List`1[System.Int64]("System.Collections.Generic.List`1[System.Int64]")

julia> list.RemoveAll(delegate(iseven, T"System.Predicate`1[System.Int64]"))
2

julia> collect(list)
3-element Vector{Int64}:
 1
 3
 5

About

Julia ❤️ .NET

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /