Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling C# method from C++ code in WP8

I'm interested in calling a C# method from C++ code in Windows Phone 8. I have already learned how to pass a callback function to C++ code from C# via delegate declarations in my C++ code, but I am looking to see if I can do any of the following:

  • Call certain methods directly from the C++ code. This would involve somehow inspecting the C# object makeup from C++, and seems unlikely to me, but I thought I'd ask you all anyway

  • Trigger events in the C# code, which can then be handled by C# methods

  • Use a dispatcher to call C# callbacks in the Main UI thread so that the callbacks can modify UI elements

  • Use a dispatcher to trigger events in the C# code, (Essentially a merging of the above two points)

In short, I am looking for as many C++ -->C# communication tips as you guys can throw me, I want to learn it all. :)

like image 880
staticfloat Avatar asked Jan 21 '13 08:01

staticfloat


People also ask

What is a calling function in C?

When a program calls a function, the program control is transferred to the called function. A called function performs a defined task and when its return statement is executed or when its function-ending closing brace is reached, it returns the program control back to the main program.

What is call by value in C?

The call by value method of passing arguments to a function copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument. By default, C programming uses call by value to pass arguments.

What is called function and calling function in C with example?

Syntax to Call a Function If function returns a value, then we can store returned value in a variable of same data type. For Example. int sum = getSum(5, 7); Above statement will call a function named getSum and pass 5 and 7 as a parameter. It also stores the return value of getSum function in variable sum.


2 Answers

By getting an object in C# code to implement a Windows RT interface, and passing down a reference to this object, it is possible to do all of the above with a bit of set-up (if I understand correctly - not sure about exactly what you want to do with your Dispatcher examples - you might want to wrap the Dispatcher on the C# side).

  1. Create a Windows Runtime component library.
  2. Define a public interface class in a C++/CX header for the C# to implement (C++ to call) (e.g. ICallback).
  3. Define a public ref class in a C++/CX header for the C++ to implement (C# to call) (e.g. CppCxClass).
  4. Add a method in CppCxClass that passes and stores an ICallback. (A C++ global variable is shown for consiseness, I recommend you review this to see if you can find a better place to store this in your code-base).

    ICallback^ globalCallback;
    ...
    void CppCxClass::SetCallback(ICallback ^callback)
    {
        globalCallback = callback;
    }
    
  5. Reference the WinRT library in your C# code.

  6. C# code: create an instance of CppCxClass using var cppObject = new CppCxClass().
  7. C# code: create a class which implements ICallback (e.g. CSharpCallbackObject).
  8. C# code: pass an instance of CSharpCallbackObject down to C++. E.g. cppObject.SetCallback(new CSharpCallbackObject()).

You can now call C# with globalCallback->CallCsharp(L"Hello C#");. You should be able to extend either ICallback and/or CppCxObject to do the rest of your tasks.

like image 153
Paul Annetts Avatar answered Oct 18 '22 18:10

Paul Annetts


After a lot of headaches trying to figure out the required code, I think it's worth posting the final version here

C++/CX

//.h
[Windows::Foundation::Metadata::WebHostHidden]
public interface class ICallback
{
public:
    virtual void Exec( Platform::String ^Command, Platform::String ^Param);
};
//.cpp
ICallback ^CSCallback = nullptr;
void Direct3DInterop::SetCallback( ICallback ^Callback)
{
    CSCallback = Callback;
}
//...

if (CSCallback != nullptr)
    CSCallback->Exec( "Command", "Param" );

C#

public class CallbackImpl : ICallback
{
    public void Exec(String Command, String Param)
    {
        //Execute some C# code, if you call UI stuff you will need to call this too
        //Deployment.Current.Dispatcher.BeginInvoke(() => { 
        // //Lambda code
        //}
    }
}
//...
CallbackImpl CI = new CallbackImpl();
D3DComponent.SetCallback( CI);
like image 36
RelativeGames Avatar answered Oct 18 '22 17:10

RelativeGames