react-nativenative-modulereact-native-native-module

React Native - Wrapping native objects created in native modules


I'm interested in wrapping some C++ libraries as react-native modules but I'm hitting a bit of a conceptual wall. Very new to this stuff so bear with me!

I want to wrap something like the AudioProcessorGraph functionality of Juce https://juce.com/doc/classAudioProcessorGraph_1_1AudioGraphIOProcessor

However a big component of the api is connecting audio node objects to each other to form an audio processing graph. You can imagine something very similar to the web audio api:

const audioCtx = new AudioContext();
const oscillator = new OscillatorNode(audioCtx);
const gainNode = new GainNode(audioCtx);

oscillator.connect(gainNode).connect(audioCtx.destination);

The problem I'm seeing, before I even write a single line of code, is that I don't see a way with the RCT_EXPORT_METHOD macro to pass an instance of a native object as an argument to a method call of another native object. https://nodejs.org/api/addons.html#addons_wrapping_c_objects I've done similar things with native node addons using the ObjectWrap functionality. Is there anyway to accomplish something similar with react-native?


Solution

  • RCT_EXPORT_METHOD is used to export a function to the JS side in IOS. The caveat here is that the arguments you pass via JS to Native or from Native to JS should be serializable. This is because the communication happens via the RN Bridge in async manner.

    This is what I would do in your case. Lets take the example:

    Lets say you have a function in native module

    //Initialise a list to store audioContexts
    ArrayList<AudioContext> audioCtxList = new ArrayList<AudioContext>();
    
    @ReactMethod
    public void createAudioContext(Callback cb){
    AudioContext audioCtx = new AudioContext();
    audioCtxList.add(audioCtx);
    cb.invoke(//...index of the newly created audioCtx)
    }
    

    Now in the JS side you have a reference that u can use to talk to native module

    so next function would look something like

    @ReactMethod
    public void createOscillator(int audioCtxId){
     AudioCtx actx = // Get the audioContext from the list using the audioCtxId
     const oscillator = new OscillatorNode(audioCtx);
     const gainNode = new GainNode(audioCtx);
     oscillator.connect(gainNode).connect(audioCtx.destination);
    }
    

    As a result you would not need to export any native object to JS side and you can accomplish the functionality u need too.