locked
Passing js callbacks into winRT cpp application

    Question

  • Hi,

    does anyone know whether it is possible to pass js function into C++ code via delegates and then invoke it:

    nearly like this:

    // js: 
    var f = function () { }

    nativeObject.setDelegate(f);

    // cpp

    public delegate void SimpleDelegate();

    void WinRTComponent::setDelegate(SimpleDelegate^ del)
    {

    del->invoke();

    }

    may be there any other methods to do such things?

    thanks in advance,

    Nick



    Monday, March 05, 2012 2:12 PM

Answers

  • Hello,

    I tested this codes and works on my side.

    // C++ codes
    // In head file
    namespace namespacedll
    {
    	public delegate int add( int a, int b);
        public ref class winRTComponent sealed
        {
    		
        public:
            winRTComponent();
    		void calldelegate(add^ func);
        };
    }
    
    // In CPP files
    winRTComponent::winRTComponent()
    {
    }
    void winRTComponent::calldelegate(add^ func)
    {
    	int res=func(3,4);
    }
    
    // In Javascript files
    var foo =  function (a, b) { return a + b };
    
    var component =new namespacedll.winRTComponent();
    component.calldelegate(foo);

    For more information. Please check the Delegates and events section in this document

    http://msdn.microsoft.com/en-us/library/windows/apps/hh441569(v=vs.110).aspx

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us


    Tuesday, March 06, 2012 5:50 AM

All replies

  • Hello,

    I tested this codes and works on my side.

    // C++ codes
    // In head file
    namespace namespacedll
    {
    	public delegate int add( int a, int b);
        public ref class winRTComponent sealed
        {
    		
        public:
            winRTComponent();
    		void calldelegate(add^ func);
        };
    }
    
    // In CPP files
    winRTComponent::winRTComponent()
    {
    }
    void winRTComponent::calldelegate(add^ func)
    {
    	int res=func(3,4);
    }
    
    // In Javascript files
    var foo =  function (a, b) { return a + b };
    
    var component =new namespacedll.winRTComponent();
    component.calldelegate(foo);

    For more information. Please check the Delegates and events section in this document

    http://msdn.microsoft.com/en-us/library/windows/apps/hh441569(v=vs.110).aspx

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us


    Tuesday, March 06, 2012 5:50 AM
  • Hi Jesse,
    thanks for you advice,

    i see now that the problem was in the "->invoke()" delegate calling.

    thanks,
      Nick


    • Edited by nicklebedev Wednesday, March 21, 2012 1:47 PM
    Wednesday, March 21, 2012 1:47 PM
  • Hi Jessie,

    How can the same be achieved in a C# RT Component,

    Can you explain with sample, I have tried but I am stuck with an error that the line where I do the function call from C# (referring to the callback function passed on from Javascript. My code in Javascript is like this,

    My.WinRT.Component.Object.processEachRowASyc(query, arguments, function(row) {
        /* Row specific processing */
    }).then(function(result) {
        /* Process after Entire Row processing is Complete */
    });

    And the code in the C# Runtime Component is like this,

    namespace mydb
    {
        public void delegate MyJSCallback(string msg);
        public class Database {
    
            public static IAsyncOperation<Database> OpenDB(string dbFile)
            {
               /* Open DB */
            }
    
            public IAsyncOperation<Database> ProcessEachRowASync(string sql,[ReadOnlyArray()] object[] arg, MyJSCallback myJSCallback)
            {
                return Task<IDataReader>.Run(() =>
                {
                /* Query Processing */
                IDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                   RowObject toRet = reader.GetMyRowObject();
                   myJSCallback(toRet);
                }
                return this;
    
                }).AsAsyncOperation();
            }
        }
    
    }

    Believe I am missing something, if you could guide me in the right direction, I will be grateful,

    Thanks in advance for your help,

    Best Regards,

    Jay


    Monday, April 29, 2013 12:53 PM
  • When I removed the IASyncOperation from the function, the js callback worked without issue.

    There seems to be a problem because I am having a blocking callback function sent as the parameter I believe. Can any one clarify how it can work with IASyncOperation present in my function.

    Regards,

    Jay

    Saturday, May 04, 2013 1:31 PM
  • when you want to call a JS function from an async context you need the main thread dispatcher for the apps window. You then use the dispatcher to call your JS method:


    save the dispatcher before you create the Task:
    CoreDispatcher^ dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher;

    Inside the task:

    dispatcher->RunAsync(CoreDispatcherPriority::Normal, handler);

    where handler is a DispatchedHandler

    • Edited by phil_ke Monday, May 13, 2013 2:32 PM
    Monday, May 13, 2013 2:31 PM