Search Unity

  1. Get the latest news, tutorials and offers directly to your inbox with our newsletters. Sign up now.
    Dismiss Notice

How to call C# methods from JavaScript?

Discussion in 'Project Tiny' started by SINePrime, Mar 14, 2020.

  1. SINePrime

    SINePrime

    Joined:
    Jan 24, 2019
    Posts:
    54
    Sorry if this is considered a duplicate of this thread, I didn't want to hijack/ necro that thread.

    I'm trying to invoke C# methods from JavaScript, and having trouble accomplishing this.

    Are we meant to use `ccall` and `cwrap`, as outlined here? When I tried to add `EXTRA_EXPORTED_RUNTIME_METHODS['cwrap']` to the arguments of my Emscripten build settings, the build tools threw an error:
    >error: Emscripten LinkerSettings contains setting for which a dedicated parameter exists: EXTRA_EXPORTED_RUNTIME_METHODS (System.InvalidOperationException)

    Is there somewhere I am meant to configure this outside the Emscripten settings?

    Another method I see is using `dynCall` methods, but documentation on these methods is scarce, and I've had no luck with all previous examples.

    I'm at a bit of a loss on how to proceed. Any ideas or documentation?
     
  2. SINePrime

    SINePrime

    Joined:
    Jan 24, 2019
    Posts:
    54
    With a bit of digging, I figured out there were multiple dynCall variants; the only variants that worked for me was the dynCall_* variant:
    Code (CSharp):
    1. dynCall_v(callback); // this works
    2. //dynCall('v', callback); // ReferenceError: dynCall is not defined
    3. //Module['dynCall_v'](callback); // TypeError: Module.dynCall_v is not a function
    I'll be sharing an example Project Tiny repo with bidirectional C# <-> JavaScript shortly.
     
    facundo_unity961 likes this.
  3. SINePrime

    SINePrime

    Joined:
    Jan 24, 2019
    Posts:
    54
    ̶I̶ ̶m̶a̶d̶e̶ ̶a̶n̶ ̶e̶x̶a̶m̶p̶l̶e̶ ̶p̶r̶o̶j̶e̶c̶t̶ ̶w̶i̶t̶h̶ ̶i̶n̶t̶e̶r̶o̶p̶e̶r̶a̶b̶i̶l̶i̶t̶y̶ ̶b̶e̶t̶w̶e̶e̶n̶ ̶C̶#̶ ̶a̶n̶d̶ ̶J̶a̶v̶a̶S̶c̶r̶i̶p̶t̶ ̶h̶e̶r̶e̶.̶ ̶T̶h̶e̶ ̶J̶a̶v̶a̶S̶c̶r̶i̶p̶t̶ ̶t̶o̶ ̶C̶#̶ ̶e̶x̶a̶m̶p̶l̶e̶s̶ ̶r̶e̶q̶u̶i̶r̶e̶ ̶y̶o̶u̶ ̶t̶o̶ ̶p̶a̶s̶s̶ ̶t̶h̶e̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶y̶o̶u̶ ̶w̶a̶n̶t̶ ̶t̶o̶ ̶c̶a̶l̶l̶ ̶a̶s̶ ̶a̶ ̶d̶e̶l̶e̶g̶a̶t̶e̶.̶

    If anyone has info on how to call an arbitrary static C# function from JavaScript in Unity, please let me know!

    EDIT: Removed project link.
     
    Last edited: Mar 4, 2021
  4. Savign

    Savign

    Joined:
    Nov 15, 2013
    Posts:
    3
    Hey Sine, thanks for putting up the example - I'm at a bit of a loss to how to call the callback methods from the javascript console though.

    If you could offer any advice that'd be greatly appreciated!
     
    Rangerz132 likes this.
  5. Rangerz132

    Rangerz132

    Joined:
    Feb 3, 2019
    Posts:
    18
    Hi @SINePrime. I'm currently building a game with Unity Tiny and I need to call C# function from JS. I'm able to call JS function from C# and to do callbacks like this => C# to JS to C#, but I'm not able to call C# function from JS. I'm not able to get the example project you mentionned earlier in your post.
     
  6. SINePrime

    SINePrime

    Joined:
    Jan 24, 2019
    Posts:
    54
    Sorry, I removed the project link because the official Getting Started guide now contains JavaScript interoperability instructions.

    As far as calling arbitrary C# from JavaScript, I don't think it's possible. You'll have to do something like pass all the C# delegates you need to JavaScript using an initialization function.
     
  7. Rangerz132

    Rangerz132

    Joined:
    Feb 3, 2019
    Posts:
    18
    I talked to one of the Tiny Dev member and said that I have to basically use the callaback approach. C# needs to give JS a callback method to use, and then JS can call it. However, I don't know how JS can call the callback..
     
  8. gtk2k

    gtk2k

    Joined:
    Aug 13, 2014
    Posts:
    154
    C# function from JS sample.

    Code (CSharp):
    1. using System;
    2. using Unity.Entities;
    3. using System.Runtime.InteropServices;
    4. using AOT;
    5.  
    6. public class MySystem : SystemBase
    7. {
    8.     delegate void FizzBuzzDelegate(int num, string fizzBuzz);
    9.  
    10.     [DllImport("__Internal")]
    11.     private static extern void callbackInit(FizzBuzzDelegate callback);
    12.  
    13.     [MonoPInvokeCallback(typeof(FizzBuzzDelegate))]
    14.     private static void FizzBuzzCallback(int num, string fizzBuzz)
    15.     {
    16.         Console.WriteLine("[C#] " + num + ":" + fizzBuzz);
    17.     }
    18.  
    19.     protected override void OnCreate()
    20.     {
    21.         callbackInit(FizzBuzzCallback);
    22.     }
    23.  
    24.     protected override void OnUpdate()
    25.     {
    26.     }
    27. }
    28.  
    Code (JavaScript):
    1. mergeInto(LibraryManager.library, {
    2.     $num: 0,
    3.     $fizzBuzzCallbackPointer: 0,
    4.  
    5.     $timerFunc: function () {
    6.         setInterval(function () {
    7.             num++;
    8.             var fizzBuzz = '';
    9.             if (!(num % 15)) fizzBuzz = 'FizzBuzz';
    10.             else if (!(num % 3)) fizzBuzz = 'Fizz';
    11.             else if (!(num % 5)) fizzBuzz = 'Buzz';
    12.             else if (!fizzBuzz) fizzBuzz = num.toString();
    13.             var len = lengthBytesUTF8(fizzBuzz) + 1;
    14.             var ptr = _malloc(len);
    15.             stringToUTF8(fizzBuzz, ptr, len);
    16.             dynCall_vii(fizzBuzzCallbackPointer, num, ptr);
    17.             _free(ptr);
    18.         }, 1000);
    19.     },
    20.  
    21.     callbackInit__deps: ['$fizzBuzzCallbackPointer', '$num', '$timerFunc'],
    22.     callbackInit: function (callbackPtr) {
    23.         fizzBuzzCallbackPointer = callbackPtr;
    24.         timerFunc();
    25.     }
    26. });
     
    Last edited: Mar 5, 2021
    Rangerz132 and Maras like this.
  9. Rangerz132

    Rangerz132

    Joined:
    Feb 3, 2019
    Posts:
    18
    Thanks a lot! I was able to do exactly what I wanted to do! It is really appreciated! Also do you know if there is a way to know if our game is LOADED in the browser and how we can UNLOAD it?
     
  10. unity_-xVksTSNs-py8g

    unity_-xVksTSNs-py8g

    Joined:
    Jul 13, 2018
    Posts:
    1
    Quick question, i'm attempting to work on a solution to this as I think there isnt a way.... but is there away to have external JS (so perhaps in the HTML page itself rather than as part of the 'mergeInto' embedded JS) call CSharp functions?
     
unityunity