azurefx / DotNET.jl

Julia ❤️ .NET

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Find and Call function in dll

gitboy16 opened this issue · comments

Hi,
Thank you for the package.
I manage to assemblies from a dll following the example in the readme file. Would you be able to tell me how I can list the functions in that dll and call it?
Thank you
Best regards

You can get whatever you want through reflection API.

julia> asm = T"System.Reflection.Assembly".LoadFrom(raw"C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\3.1.18\System.Windows.Forms.dll")
System.Reflection.RuntimeAssembly("System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")

julia> asm.ExportedTypes |> collect
1021-element Array{CLRObject,1}:
 System.Drawing.Design.IPropertyValueUIService
 System.Drawing.Design.PaintValueEventArgs
 System.Drawing.Design.PropertyValueUIHandler
 System.Drawing.Design.PropertyValueUIItem
 System.Drawing.Design.PropertyValueUIItemInvokeHandler
 System.Drawing.Design.UITypeEditor
 System.Drawing.Design.UITypeEditorEditStyle
 ⋮
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+SmallCaptionSizingTemplate
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+FrameLeftSizingTemplate
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+SmallFrameLeftSizingTemplate
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+FrameRightSizingTemplate
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+SmallFrameRightSizingTemplate
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+FrameBottomSizingTemplate
 System.Windows.Forms.VisualStyles.VisualStyleElement+Window+SmallFrameBottomSizingTemplate

julia> Form = T"System.Windows.Forms.Form, System.Windows.Forms"
System.Windows.Forms.Form

julia> Form.GetMembers() |> collect
720-element Array{CLRObject,1}:
 System.Reflection.RuntimeMethodInfo("Void SetDesktopBounds(Int32, Int32, Int32, Int32)")
 System.Reflection.RuntimeMethodInfo("Void SetDesktopLocation(Int32, Int32)")
 System.Reflection.RuntimeMethodInfo("Void Show(System.Windows.Forms.IWin32Window)")
 System.Reflection.RuntimeMethodInfo("System.Windows.Forms.DialogResult ShowDialog()")
 System.Reflection.RuntimeMethodInfo("System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.IWin32Window)")
 System.Reflection.RuntimeMethodInfo("System.String ToString()")
 System.Reflection.RuntimeMethodInfo("Boolean ValidateChildren()")
 ⋮
 System.Reflection.RuntimeEventInfo("System.EventHandler SystemColorsChanged")
 System.Reflection.RuntimeEventInfo("System.ComponentModel.CancelEventHandler Validating")
 System.Reflection.RuntimeEventInfo("System.EventHandler Validated")
 System.Reflection.RuntimeEventInfo("System.EventHandler ParentChanged")
 System.Reflection.RuntimeEventInfo("System.EventHandler ImeModeChanged")
 System.Reflection.RuntimeEventInfo("System.EventHandler Disposed")
 System.Windows.Forms.Form+ControlCollection

See also: #11

Thank you. I manage to find the function I wanted. When I call it, it returns me the following:

System.Object[,,]("System.Object[,,]")

I am not sure what that is.
Is there a way to read the output in a Julia object ...like matrix, vector or anything else?

Also is there a way to create such an object from Julia and pass it to a function in the dll.

I am not sure what that is.

It is just a multidimensional array with a rank of 3. All array types are subtypes of System.Array.

julia> isassignable(T"System.Array", T"System.Int32[,,]")
true

julia> isassignable(T"System.Int32[,,]", T"System.Array")
false

Is there a way to read the output in a Julia object ...like matrix, vector or anything else?

We have collect function that converts .NET arrays to Julia arrays.

However, n-d arrays are not fully supported now, so they become 1-d arrays when you collect them. You can usereshape function to recover dimension sizes.

public static int[,,] Get3DArray() {
  return new int[2, 2, 2] {
    {{1, 2}, {3, 4}},
    {{5, 6}, {7, 8}}
  };
}
julia> a = YourClass.Get3DArray()
System.Int32[,,]("System.Int32[,,]")

julia> collect(a)
8-element Array{Int32,1}:
 1
 2
 3
 4
 5
 6
 7
 8

julia> reshape(ans, 2, 2, 2)
2×2×2 Array{Int32,3}:
[:, :, 1] =
 1  3
 2  4

[:, :, 2] =
 5  7
 6  8

Other useful methods for .NET arrays:

julia> clrtypeof(a) # returns a CLR Type object
System.Int32[,,]

julia> clreltype(a) # returns the element type of a CLR array
System.Int32

julia> eltype(a) # returns the element type in Julia, if the array is collected
Int32

julia> a.GetValue(Int32[1,0,1]) # to access the n-d array without collecting
6

Also is there a way to create such an object from Julia and pass it to a function in the dll.

Yes, just pass the object to the function.

julia> b = reshape(1:8, 2, 2, 2)
2×2×2 reshape(::UnitRange{Int64}, 2, 2, 2) with eltype Int64:
[:, :, 1] =
 1  3
 2  4

[:, :, 2] =
 5  7
 6  8

julia> Console.WriteLine(b);
System.Int64[,,]

If you want an uninitialized array, there is a convenient function:

julia> DotNET.arrayof(T"System.Int32", (2, 2, 2))
System.Int32[,,]("System.Int32[,,]")

Thank you. The above is very useful.
Let's say I have the following:

julia> data = DotNET.arrayof(T"System.Object",(2,2,2))
System.Object[,,]("System.Object[,,]")

julia> data |> collect
8-element Vector{CLRObject}:
null
null
null
null
null
null
null
null

How do I actually add values in that vector?
(I want the array to be initilised with values)

Not sure if it can help but when I call some function in the dll I get something like that:

julia> Form.getIDs("")
System.Object[,,]("System.Object[,,]")

julia> Form.getIDs("") |> collect
4-element Vector{CLRObject}:
System.String("bi_id")
System.String("name")
System.String("internal")
System.String("external")

Thank you in advance.

arraystore can do the job, which I forgot to mention.

julia> data = DotNET.arrayof(T"System.Object", (2, 2, 2))
System.Object[,,]("System.Object[,,]")

julia> DotNET.arraystore(data, (0, 0, 0), "bi_id")
null

julia> DotNET.arrayload(data, (0, 0, 0))
"bi_id"

julia> collect(data)
8-element Array{CLRObject,1}:
 System.String("bi_id")
 null
 null
 null
 null
 null
 null
 null

Note: In case you have a CLRObject that represents a primitive type (aka "boxed"), you can call unbox to retrieve the underlying data:

julia> collect(data)[1]
System.String("bi_id")

julia> DotNET.unbox(ans)
"bi_id"

Since Julia does not distinguish between boxed and unboxed types, values returned from .NET functions are automatically unboxed. So far, the collect function is not recursive, and I wonder if this should be changed in the future...

You are a star. Thank you very much. I think it is worth saving the above in a manual or wiki as it can be useful to others. Feel free to close this "issue".

Hi, I hope you are well. I was wondering how hard would it be to support n-d arrays so it is possible know what is the real dimension of the arrays returned? Right now I have to guess it which is a bit of an issue. Thank you.

Supported in v0.2.0, README updated.

You are the best. Thank you.