Skip to content

Commit 9a38adf

Browse files
Update README.md
1 parent 0be9a42 commit 9a38adf

File tree

1 file changed

+45
-204
lines changed

1 file changed

+45
-204
lines changed

README.md

Lines changed: 45 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -1,237 +1,78 @@
1-
# JULIAdotNET
1+
# JdotNET
22

3-
JuliadotNET is an API designed to go between .NET and the Julia Language. It utilizes C Intefaces of both languages to allow super efficient transfers between languages (however it does have type conversion overhead as expected).
3+
JdotNET is an API designed to go between .NET and the Julia Language. It utilizes C Intefaces of both languages to allow super efficient transfers between languages (type conversion overhead is expected in using nonspecialized (Any types for instance) functions).
44

55

6-
##Julia Interface from C#
6+
## Static Library Generator
7+
**In Development**
8+
This project generates a .NET dll that statically creates a snapshot of a julia Module and all its submodules and allows for static analysis from csharp. This library will use the most efficient techniques (caching constants, specializing functions and using cfunctions when it can) to provide for the most efficient calls to julia.
79

8-
### Launching Julia
9-
```csharp
10-
JuliaOptions options = new JuliaOptions();
11-
options.ThreadCount = 4;
12-
Julia.Init(options);
13-
```
14-
15-
### Evaluation
16-
```csharp
17-
Julia.Init();
18-
int v = (int) Julia.Eval("2 * 2");
19-
Julia.Exit(0); //Even if your program terminates after you should call this. It runs the finalizers and stuff
20-
```
21-
22-
### Structs
23-
```csharp
24-
25-
#You have two choices, allocate a struct or create a struct.
26-
#Allocating directly sets the memory, creating will call a constructor of the struct
27-
28-
var myAllocatedStruct = Julia.AllocStruct(JLType.JLRef, 3); //Will throw error
29-
var myCreatedStuct = JLType.JLRef.Create(3); //Will call constructor
30-
```
31-
32-
### Functions
10+
Example using Base.dll:
3311
```csharp
34-
JLFun fun = Julia.Eval("t(x::Int) = Int32(x * 2)");
35-
JLSvec ParameterTypes = fun.ParameterTypes;
36-
JLType willbeInt64 = fun.ParameterTypes[1];
37-
JLType willBeInt32 = fun.ReturnType;
38-
39-
JLVal resultWillBe4 = fun.Invoke(2);
40-
```
41-
42-
### Values
43-
```csharp
44-
//Auto alloc to Julia
45-
var val = new JLVal(3);
46-
47-
//Manual Type Unboxing
48-
long netVal = val.UnboxInt64();
12+
using Base;
4913

50-
//Auto Unboxing
51-
object newVal2 = val.Value;
14+
Base.println("My Function"); //This function will be statically available
5215
```
5316

54-
### Arrays
55-
```csharp
56-
JLArray arr = Julia.Eval("[2, 3, 4]")
57-
58-
//Unpack to .net
59-
object[] o = arr.UnboxArray();
60-
61-
var a = new int[]{2, 3, 4};
62-
63-
//Copy to a Julia Array. Dont use this method if you know an object is an array though. There are faster methods!
64-
var v = new JLVal(a);
65-
66-
//Fast Array Copy From .NET. This will deal with direct memory transfer rather then boxing/unboxing for unmanaged types
67-
var v2 = JLArray.CreateArray(a);
68-
69-
//Fast Array Copy From Julia. This will deal with direct memory transfer rather then boxing/unboxing for unmanaged types
70-
int[] v2 = v2.UnboxArray<int>();
71-
72-
JLType elementType = arr.ElType;
73-
```
17+
## Dynamics
18+
**In Development**
19+
Some code may be dynamically generated in julia and thus cannot be represented using the static library generator. This project will provide an abstract layer to the underlying JdotNET net-julia interface to provide more seamless usage.
7420

75-
### Exception Handling
7621
```csharp
77-
JLFun fun = Julia.Eval("t(x) = sqrt(x)");
78-
fun.Invoke(5).Println(); //Exception Checking
79-
fun.UnsafeInvoke(5).Println(); //No Exception Checking
80-
Julia.Exit(0);
22+
dynamic Base = JPrimitive.BaseM;
23+
Base.println("My Function"); //JdotNET will dynamically resolve and cache this function. It is extremely recommended to locally cache functions outside loops.
8124
```
8225

26+
##JdotNet Julia-Net Interface#
8327

84-
### Garbage Collection
85-
You are (at the current moment of this project) responsible for ensuring object safety on both .NET and Julia. When you make calls to either language, the GC could activate and invalidate the reference you hold in the other language unless you pin it!
86-
87-
There are two forms of Garbage Collector Pinning: Static & Stack.
88-
89-
Static pinning is meant for objects with a long life span (could exist forever).
90-
Stack pinning is meant for objects with a short life span.
91-
92-
### CSharp Static Garbage Collector Pinning
28+
### Launching Julia
9329
```csharp
94-
JLArray myArr = new JLArray(JLType.Int64, 5); //Allocate Int64 array of length 5
95-
96-
var handle = myArr.Pin(); //Pin the Object
97-
98-
//Stuff calling Julia Functions
99-
100-
handle.Free(); //Optional, handle destructor will auto call it. This is in case you want it freed earlier
30+
JuliaOptions options = new JuliaOptions();
31+
options.ThreadCount = 4;
32+
Julia.Init(options);
10133
```
10234

103-
### CSharp Stack Garbage Collector Pinning
35+
### Evaluation
10436
```csharp
105-
JLVal v = Julia.Eval("2 * 2");
106-
JLVal v2 = Julia.Eval("Hi");
107-
Julia.GC_PUSH(v, v2);
108-
109-
//Do Stuff with v without it being collected
110-
111-
Julia.GC_POP();
37+
Julia.Init();
38+
int v = (int) Julia.Eval("2 * 2");
39+
Julia.Exit(0); //Even if your program terminates after you should call this. It runs the finalizers and stuff
11240
```
11341

114-
## C# from Julia
115-
116-
The Julia.NET API also has a reverse calling API to call .NET from Julia. This also uses the C interface making it super fast (compared to message protocol based language interop systems. It depends on reflection which is the factor that slows it down compared to normal C# code). Drew ideas of syntax from https://github.com/azurefx/DotNET.jl
42+
### Any
43+
The Any class represents a boxed Julia value. There is many built in default conversions from native NET types to the Any type which can be utilized via the Any constructor.
11744

118-
### Launching C# from Julia
119-
```julia
120-
using JULIAdotNET
121-
using JULIAdotNET.JuliaInterface
122-
123-
handle = Init() #Keep handle alive as long as you want .NET to be alive
124-
125-
sharpList = T"System.Collections.Generic.List`1".new[T"System.Int64"]()
126-
```
127-
128-
Lets say we have the following C# classes:
12945
```csharp
130-
namespace Test{
131-
public class ReflectionTestClass{
132-
public long g;
133-
public static int TestStaticField = 5;
134-
public ReflectionTestClass(long g) { this.g = g; }
135-
public long InstanceMethod() => 5;
136-
public static long StaticMethod() => 5;
137-
public static long StaticGenericMethod<T>() => 3;
138-
}
139-
140-
public class ReflectionGenericTestClass<T>
141-
{
142-
public T g;
143-
public ReflectionGenericTestClass(T g) { this.g = g; }
144-
}
145-
}
146-
```
147-
148-
### Accessing Sharp Types From Julia
149-
The Sharp Type object allows one to access .NET class fields, methods and constructors from julia
150-
```julia
151-
myClass = T"Test.ReflectionTestClass" #<= Perform Assembly Search and Return the Sharp Type
152-
153-
myClass2 = P"Test.ReflectionTestClass" #<= Perform one time assembly search and store the sharp type in a internal array (Reccommended for fast lookups)
154-
155-
myClass3 = G"Test.ReflectionTestClass" #Get from internal array
46+
Julia.Init();
47+
var v25 = new Any(5) * 5; //The second 5 will be auto converted to Any then the operator '*' will be invoked on both arguments
15648
157-
myClass4 = R"Test.ReflectionTestClass" #Remove from internal array
158-
```
159-
160-
The using statement From Julia enables a user to shorten the length of a type name required
161-
```julia
162-
myClass1 = T"System.Int64" #<= Will Work But It is long to type
163-
myClass2 = T"Int64" #<= Will Fail
164-
@netusing System
165-
myClass3 = T"Int64" #<= Will Work
166-
```
167-
168-
### Field Invokation
169-
```julia
170-
@netusing Test
171-
shouldBe5 = T"ReflectionTestClass".TestStateField[] #< Requires [] to actually get the field. If you dont put [] or () then it will just return the FieldInfo object
172-
173-
T"ReflectionTestClass".TestStateField[] = 3 #To Set a Field. An error will occur if you dont put [].
174-
```
175-
176-
### Method Invokation
177-
```julia
178-
@netusing Test
179-
@netusing System
180-
shouldBe5 = T"ReflectionTestClass".TestStateField[] #< Requires [] to actually get the field. If you dont put [] or () then it will just return the FieldInfo object
181-
shouldBe5 = T"ReflectionTestClass".StaticMethod[]() #To call a method. If you dont put [] or () then it will just return the MethodInfo object
182-
shouldBe3 = T"ReflectionTestClass".StaticGenericMethod[T"Int64"]() "To call a generic method, put the generic types in []
183-
```
184-
185-
### Constructor Invokation
186-
```julia
187-
@netusing Test
188-
@netusing System
189-
item = T""TestJuliaInterface.ReflectionTestClass"".new[](3) #To call a constructor. If you dont put [] or () then it will just return the ConstructorInfo object
190-
shouldBe5 = item.InstanceMethod[](); #To call a instance method
49+
//Arrays are passed by pointer value so there is no copying cost. Keep in mind that if julia mutates the array, it will also be affected in c#
50+
var myNetArray = new []{1, 2, 3, 4, 5};
51+
var myJuliaArray = new Any(myNetArray);
52+
Julia.Eval("f(x) = x .* 2").Invoke(myJuliaArray);
53+
//myNetArray will now be {2, 4, 6, 8, 10}
19154
192-
shouldBe3 = item.g[] #To Access a instance field
55+
//Search for a Julia Module lets say its called Main.MyModule:
56+
var myModule = JPrimitive.MainM.GetGlobal("MyModule");
19357

194-
myGenericItem = T"TestJuliaInterface.ReflectionGenericTestClass`1".new[T"System.Int64"](3) #To Create a generic instance of an object, put the generic types in [].
58+
//Search for Function add! in MyModule
59+
var add = myModule.GetFunction("add!");
19560

196-
```
197-
198-
### Boxing/Unboxing
199-
Boxing/Unboxing is converting a julia value from/to a sharp value from julia
200-
```julia
201-
boxed5 = sharpbox(5) #Will return the sharp object of the long value "5"
202-
shouldBe5 = shapunbox(boxed5) #Will unbox the sharp object and return to native julia value
203-
```
204-
205-
### Julia Garbage Collector Pinning
206-
```julia
207-
handle = pin(sharpbox(5))
208-
#Stuff calling Sharp Functions
209-
free(handle) #Will also auto free. You can also treat it like stream and put it in do end block
210-
```
211-
212-
## Exposing custom functions as native functions to julia
213-
### From C#
214-
```csharp
215-
public unsafe delegate IntPtr JuliaNativeInterface(IntPtr* data);
61+
//You have several choices of invoking add
62+
//The first is using Invoke. This is the safest way to invoke as it provides features like exception handling
63+
add.Invoke(2, 2);
21664

217-
//Example from NativeSharp.cs that we want to expose to julia
218-
public static JLVal /*Use this to manipulate julia objects to/from julia*/ GetMethod(NativeObject<Type> /*Use this to manipulate sharp objects to/from julia*/ t, NativeString /*Transfer strings*/ name) => GetMethod(t.Value, name.Value);
65+
//The second is using Unsafe Invoke. This is unsafe and should only be used in time critcal code that is stable.
66+
add.UnsafeInvoke(2, 2);
21967

220-
//Register the method. You must increment the pointer for each argument left to right
221-
NativeSharp.RegisterSharpFunction("GetMethodByName", data => GetMethod(data++, data));
222-
```
223-
### From julia
224-
```julia
225-
//Generate the function and insert it into current module
226-
Function Name Function Arguments Exposed to Julia Convert to Native Objects
227-
@sharpfunction(GetMethodByName, (type::SharpType, name::AbstractString), (NativeObject(type), NativeString(name)))
68+
//The final way which is still in development is retrieving the function as a native delegate pointer into .net and invoking it directly.
69+
Func<int, int, int> f = add.GetDelegate<int, int, int>();
70+
f(2, 2); //Fastest way to invoke but it is also unsafe. You should periodically check for exceptions when using this.
71+
Julia.CheckExceptions();
22872

229-
//Using the function
230-
someRandomType::SharpType
231-
sharpMethod = GetMethodByName(someRandomType, "MyMethod")
73+
Julia.Exit(0);
23274
```
23375

234-
23576
## Contributing
23677
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
23778

0 commit comments

Comments
 (0)