• Garuda/Eagle in starpack

    From Harald Oehlmann@21:1/5 to All on Mon Sep 13 10:41:18 2021
    Am 13.09.2021 um 10:20 schrieb Yusuke Yamasaki:
    Is it possible for a starpack-wrapped Tcl/Tk application to use external
    .NET assemblies using Garuda? I use the latest build (1.0.7900.33333, 2021-08-23).

    My Tcl/Tk application is wrapped into a starpack with ActiveState
    TclApp. I wanted to check if Garuda can work with my app.

    Ideally, I want to embed Eagle.dll and Garuda.dll into my starpack but
    at first, I just installed Eagle/Garuda binaries to the lib folder under
    the working directory and inserted the path to the head of ::auto_path.

    The purpose to use Garuda is to load an external managed assembly from
    the local sub-folder. The assembly is dependent on several DLLs in the
    same folder. I keep them out of my starpack.

    + lib\
      + Garuda-1.0\
        + dotnet.tcl
        + Eagle.dll
        + Garuda.dll
        + helper.tcl
        + pkgIndex.tcl
    + RemoteClient\
      + Google.Protobuf.dll
      + Grpc.Core.Api.dll
      + Grpc.Core.dll
      + grcp_csharp_ext.x86.dll
      + GRPCRemoteClient.dll (This is the DLL to be loaded from MyApp.tcl)
      + System.Buffers.dll
      + System.Memory.dll
      + System.Numerics.Vectors.dll
      + System.Runtime.CompilerServices.Unsafe.dll
    + MyApp.tcl

    MyApp.tcl is the main script. It loads Garuda.
    The eagle command loads RemoteClient\GRPCRemoteClient.dll and the
    classes and the methods are used.

    If MyApp.tcl is not wrapped into a starkit, it works well.
    However, if it is wrapped, it can't create any instance of classes
    defined inside GRPCRemoteClient.dll, although it seemed to load GRPCRemoteClient.dll successfully.

    I followed the instruction in this article and added
    METHOD_PROTOCOL_V1R2 flag before loading Garuda package.

    https://wiki.tcl-lang.org/page/Garuda.

    # MyApp.tcl

    set exehome [pwd]

    set auto_path [linsert $auto_path 0 [file join $::exehome lib]]

    namespace eval ::Garuda {
        variable methodFlags 0x40; # METHOD_PROTOCOL_V1R2
    }
    package require Garuda
    eagle {
        set dll_dir "./GRPCRemoteClient"
        set dll_file "GRPCRemoteClient.dll"
        set dll_path [file join $dll_dir $dll_file]
        object invoke System.Reflection.Assembly LoadFrom $dll_path
    }
    # => {GRPCRemoteClient, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} c199bf34-6a72-4256-8e1c-5857959232ad 293
    # => Seemed successful.

    eagle {
        object create -alias GRPCRemote.GRPCRemoteClient "127.0.0.1" 50051
    }
    # => {type "GRPCRemote.GRPCRemoteClient" not found} {expected type value
    but got "GRPCRemote.GRPCRemoteClient"}
    # => Failed.


    Yusuke Yamasaki <tm9233yy@gmail.com>

    Dear Yusuke,

    thank you for the question. Your work looks great. I have never used
    Garunda but have implemented .net DLL's using C++ code in a DLL witten
    by me and called by TCL.

    I can only report from my personal experiences about DLL's loading other
    DLL's. It does not make any difference, if it is a .net dll or a C dll.
    The observed mechansim is the same.

    When a dll is packed into a starpack, its invocation happens like that:
    - copy the dll to the tmp folder (with a funny tmp name)
    - load it with the load command and the foll path.

    That works well, but if the dll loads other dll's, they are often not
    found, as the dll location should be beside the calling dll or beside
    the executable (or in the system folders). I did not find any way to
    control this mechanism from the C side. I had no control over the .net
    library.

    So, I found two solutions which are not beautiful:
    - put the TCL DLL in the starkit but the depenedent DLL's beside the executable.
    - put the TCL DLL in a subfolder (I use lib) and put all dependent DLL's
    in the same folder.

    Sorry, only my two pennies,
    Harald

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Yusuke Yamasaki@21:1/5 to All on Mon Sep 13 17:20:45 2021
    Is it possible for a starpack-wrapped Tcl/Tk application to use external
    .NET assemblies using Garuda? I use the latest build (1.0.7900.33333, 2021-08-23).

    My Tcl/Tk application is wrapped into a starpack with ActiveState
    TclApp. I wanted to check if Garuda can work with my app.

    Ideally, I want to embed Eagle.dll and Garuda.dll into my starpack but
    at first, I just installed Eagle/Garuda binaries to the lib folder under
    the working directory and inserted the path to the head of ::auto_path.

    The purpose to use Garuda is to load an external managed assembly from
    the local sub-folder. The assembly is dependent on several DLLs in the
    same folder. I keep them out of my starpack.

    + lib\
    + Garuda-1.0\
    + dotnet.tcl
    + Eagle.dll
    + Garuda.dll
    + helper.tcl
    + pkgIndex.tcl
    + RemoteClient\
    + Google.Protobuf.dll
    + Grpc.Core.Api.dll
    + Grpc.Core.dll
    + grcp_csharp_ext.x86.dll
    + GRPCRemoteClient.dll (This is the DLL to be loaded from MyApp.tcl)
    + System.Buffers.dll
    + System.Memory.dll
    + System.Numerics.Vectors.dll
    + System.Runtime.CompilerServices.Unsafe.dll
    + MyApp.tcl

    MyApp.tcl is the main script. It loads Garuda.
    The eagle command loads RemoteClient\GRPCRemoteClient.dll and the
    classes and the methods are used.

    If MyApp.tcl is not wrapped into a starkit, it works well.
    However, if it is wrapped, it can't create any instance of classes
    defined inside GRPCRemoteClient.dll, although it seemed to load GRPCRemoteClient.dll successfully.

    I followed the instruction in this article and added
    METHOD_PROTOCOL_V1R2 flag before loading Garuda package.

    https://wiki.tcl-lang.org/page/Garuda.

    # MyApp.tcl

    set exehome [pwd]

    set auto_path [linsert $auto_path 0 [file join $::exehome lib]]

    namespace eval ::Garuda {
    variable methodFlags 0x40; # METHOD_PROTOCOL_V1R2
    }
    package require Garuda
    eagle {
    set dll_dir "./GRPCRemoteClient"
    set dll_file "GRPCRemoteClient.dll"
    set dll_path [file join $dll_dir $dll_file]
    object invoke System.Reflection.Assembly LoadFrom $dll_path
    }
    # => {GRPCRemoteClient, Version=1.0.0.0, Culture=neutral,
    PublicKeyToken=null} c199bf34-6a72-4256-8e1c-5857959232ad 293
    # => Seemed successful.

    eagle {
    object create -alias GRPCRemote.GRPCRemoteClient "127.0.0.1" 50051
    }
    # => {type "GRPCRemote.GRPCRemoteClient" not found} {expected type value
    but got "GRPCRemote.GRPCRemoteClient"}
    # => Failed.


    Yusuke Yamasaki <tm9233yy@gmail.com>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Harald Oehlmann@21:1/5 to All on Mon Sep 13 10:52:27 2021
    Am 13.09.2021 um 10:41 schrieb Harald Oehlmann:

    Am 13.09.2021 um 10:20 schrieb Yusuke Yamasaki:
    Is it possible for a starpack-wrapped Tcl/Tk application to use
    external .NET assemblies using Garuda? I use the latest build
    (1.0.7900.33333, 2021-08-23).

    My Tcl/Tk application is wrapped into a starpack with ActiveState
    TclApp. I wanted to check if Garuda can work with my app.

    Ideally, I want to embed Eagle.dll and Garuda.dll into my starpack but
    at first, I just installed Eagle/Garuda binaries to the lib folder
    under the working directory and inserted the path to the head of
    ::auto_path.

    The purpose to use Garuda is to load an external managed assembly from
    the local sub-folder. The assembly is dependent on several DLLs in the
    same folder. I keep them out of my starpack.

    + lib\
       + Garuda-1.0\
         + dotnet.tcl
         + Eagle.dll
         + Garuda.dll
         + helper.tcl
         + pkgIndex.tcl
    + RemoteClient\
       + Google.Protobuf.dll
       + Grpc.Core.Api.dll
       + Grpc.Core.dll
       + grcp_csharp_ext.x86.dll
       + GRPCRemoteClient.dll (This is the DLL to be loaded from MyApp.tcl)
       + System.Buffers.dll
       + System.Memory.dll
       + System.Numerics.Vectors.dll
       + System.Runtime.CompilerServices.Unsafe.dll
    + MyApp.tcl

    MyApp.tcl is the main script. It loads Garuda.
    The eagle command loads RemoteClient\GRPCRemoteClient.dll and the
    classes and the methods are used.

    If MyApp.tcl is not wrapped into a starkit, it works well.
    However, if it is wrapped, it can't create any instance of classes
    defined inside GRPCRemoteClient.dll, although it seemed to load
    GRPCRemoteClient.dll successfully.

    I followed the instruction in this article and added
    METHOD_PROTOCOL_V1R2 flag before loading Garuda package.

    https://wiki.tcl-lang.org/page/Garuda.

    # MyApp.tcl

    set exehome [pwd]

    set auto_path [linsert $auto_path 0 [file join $::exehome lib]]

    namespace eval ::Garuda {
         variable methodFlags 0x40; # METHOD_PROTOCOL_V1R2
    }
    package require Garuda
    eagle {
         set dll_dir "./GRPCRemoteClient"
         set dll_file "GRPCRemoteClient.dll"
         set dll_path [file join $dll_dir $dll_file]
         object invoke System.Reflection.Assembly LoadFrom $dll_path
    }
    # => {GRPCRemoteClient, Version=1.0.0.0, Culture=neutral,
    PublicKeyToken=null} c199bf34-6a72-4256-8e1c-5857959232ad 293
    # => Seemed successful.

    eagle {
         object create -alias GRPCRemote.GRPCRemoteClient "127.0.0.1" 50051 >> }
    # => {type "GRPCRemote.GRPCRemoteClient" not found} {expected type
    value but got "GRPCRemote.GRPCRemoteClient"}
    # => Failed.


    Yusuke Yamasaki <tm9233yy@gmail.com>

    Dear Yusuke,

    thank you for the question. Your work looks great. I have never used
    Garunda but have implemented .net DLL's using C++ code in a DLL witten
    by me and called by TCL.

    I can only report from my personal experiences about DLL's loading other DLL's. It does not make any difference, if it is a .net dll or a C dll.
    The observed mechansim is the same.

    When a dll is packed into a starpack, its invocation happens like that:
    - copy the dll to the tmp folder (with a funny tmp name)
    - load it with the load command and the foll path.

    That works well, but if the dll loads other dll's, they are often not
    found, as the dll location should be beside the calling dll or beside
    the executable (or in the system folders). I did not find any way to
    control this mechanism from the C side. I had no control over the .net library.

    So, I found two solutions which are not beautiful:
    - put the TCL DLL in the starkit but the depenedent DLL's beside the executable.
    - put the TCL DLL in a subfolder (I use lib) and put all dependent DLL's
    in the same folder.

    Sorry, only my two pennies,
    Harald

    I have to add, that you may unpack all DLL's and depending DLL's from
    the starpack. You may also look to my post on the Wiki on cleaning-up
    the temporary DLL's, as a new copy is created on each start-up.

    Take care,
    Harald

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Yusuke Yamasaki@21:1/5 to Harald Oehlmann on Mon Sep 13 21:01:49 2021
    Dear Harald,

    Thank you for your response.

    Actually, MyApp.exe (not MyApp.tcl, sorry for my typo.) is a wrapped
    Tcl/Tk application. And it doesn't wrap Garuda and managed DLLs because
    I knew that DLLs except for the ones built as Tcl extensions normally
    can't be loaded from temporary folders as you pointed out. They are in
    normal folders under the working folder (./RemoteClient/*).

    I also use native DLLs written in C++ with C-style export functions and
    I load it from the working directory using Ffidl not from starpack's
    temporary folders and it works well. Although it is not beautiful, I
    decided to follow the same way because the important point for me is to
    make it work somehow. However, it didn't work... That's why I posted
    this question here.

    I think your's is so called a mixed-mode assembly written in C++/CLI.
    So I guess the interface is a C-style export function isn't it?
    The difference I can think of is the the interface whether it is loaded
    by Garuda or by a foreign function call library.

    + lib\
    + Garuda-1.0\
    + dotnet.tcl
    + Eagle.dll
    + Garuda.dll
    + helper.tcl
    + pkgIndex.tcl
    + RemoteClient\
    + Google.Protobuf.dll
    + Grpc.Core.Api.dll
    + Grpc.Core.dll
    + grcp_csharp_ext.x86.dll
    + GRPCRemoteClient.dll (This is the DLL to be loaded from MyApp.tcl)
    + System.Buffers.dll
    + System.Memory.dll
    + System.Numerics.Vectors.dll
    + System.Runtime.CompilerServices.Unsafe.dll
    + MyApp.exe

    Regards,
    Yusuke


    On 2021/09/13 17:52, Harald Oehlmann wrote:

    Dear Yusuke,

    thank you for the question. Your work looks great. I have never used
    Garunda but have implemented .net DLL's using C++ code in a DLL witten
    by me and called by TCL.

    I can only report from my personal experiences about DLL's loading
    other DLL's. It does not make any difference, if it is a .net dll or a
    C dll. The observed mechansim is the same.

    When a dll is packed into a starpack, its invocation happens like that:
    - copy the dll to the tmp folder (with a funny tmp name)
    - load it with the load command and the foll path.

    That works well, but if the dll loads other dll's, they are often not
    found, as the dll location should be beside the calling dll or beside
    the executable (or in the system folders). I did not find any way to
    control this mechanism from the C side. I had no control over the .net
    library.

    So, I found two solutions which are not beautiful:
    - put the TCL DLL in the starkit but the depenedent DLL's beside the
    executable.
    - put the TCL DLL in a subfolder (I use lib) and put all dependent
    DLL's in the same folder.

    Sorry, only my two pennies,
    Harald

    I have to add, that you may unpack all DLL's and depending DLL's from
    the starpack. You may also look to my post on the Wiki on cleaning-up
    the temporary DLL's, as a new copy is created on each start-up.

    Take care,
    Harald

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Harald Oehlmann@21:1/5 to All on Mon Sep 13 14:33:38 2021
    Dear Yusuke,

    what you write sounds completly reasonable. I suppose, I can not help
    you any further.
    Take care,
    Harald

    Am 13.09.2021 um 14:01 schrieb Yusuke Yamasaki:
    Dear Harald,

    Thank you for your response.

    Actually, MyApp.exe (not MyApp.tcl, sorry for my typo.) is a wrapped
    Tcl/Tk application. And it doesn't wrap Garuda and managed DLLs because
    I knew that DLLs except for the ones built as Tcl extensions normally
    can't be loaded from temporary folders as you pointed out. They are in
    normal folders under the working folder (./RemoteClient/*).

    I also use native DLLs written in C++ with C-style export functions and
    I load it from the working directory using Ffidl not from starpack's temporary folders and it works well. Although it is not beautiful, I
    decided to follow the same way because the important point for me is to
    make it work somehow. However, it didn't work... That's why I posted
    this question here.

    I think your's is so called a mixed-mode assembly written in C++/CLI.
    So I guess the interface is a C-style export function isn't it?
    The difference I can think of is the the interface whether it is loaded
    by Garuda or by a foreign function call library.

    + lib\
      + Garuda-1.0\
        + dotnet.tcl
        + Eagle.dll
        + Garuda.dll
        + helper.tcl
        + pkgIndex.tcl
    + RemoteClient\
      + Google.Protobuf.dll
      + Grpc.Core.Api.dll
      + Grpc.Core.dll
      + grcp_csharp_ext.x86.dll
      + GRPCRemoteClient.dll (This is the DLL to be loaded from MyApp.tcl)
      + System.Buffers.dll
      + System.Memory.dll
      + System.Numerics.Vectors.dll
      + System.Runtime.CompilerServices.Unsafe.dll
    + MyApp.exe

    Regards,
    Yusuke


    On 2021/09/13 17:52, Harald Oehlmann wrote:

    Dear Yusuke,

    thank you for the question. Your work looks great. I have never used
    Garunda but have implemented .net DLL's using C++ code in a DLL
    witten by me and called by TCL.

    I can only report from my personal experiences about DLL's loading
    other DLL's. It does not make any difference, if it is a .net dll or
    a C dll. The observed mechansim is the same.

    When a dll is packed into a starpack, its invocation happens like that:
    - copy the dll to the tmp folder (with a funny tmp name)
    - load it with the load command and the foll path.

    That works well, but if the dll loads other dll's, they are often not
    found, as the dll location should be beside the calling dll or beside
    the executable (or in the system folders). I did not find any way to
    control this mechanism from the C side. I had no control over the
    .net library.

    So, I found two solutions which are not beautiful:
    - put the TCL DLL in the starkit but the depenedent DLL's beside the
    executable.
    - put the TCL DLL in a subfolder (I use lib) and put all dependent
    DLL's in the same folder.

    Sorry, only my two pennies,
    Harald

    I have to add, that you may unpack all DLL's and depending DLL's from
    the starpack. You may also look to my post on the Wiki on cleaning-up
    the temporary DLL's, as a new copy is created on each start-up.

    Take care,
    Harald


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Yusuke Yamasaki@21:1/5 to Harald Oehlmann on Tue Sep 14 00:08:44 2021
    Dear Harald,

    I found that Eagle has a public forum. I will ask this question there.
    Anyway, thank you for your comments.

    Regards,
    Yusuke


    On 2021/09/13 21:33, Harald Oehlmann wrote:
    Dear Yusuke,

    what you write sounds completly reasonable. I suppose, I can not help
    you any further.
    Take care,
    Harald


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)