Home > database >  Is there the ways to forward output from XCode to Processing?
Is there the ways to forward output from XCode to Processing?

Time:11-14

I'm trying out to forward output stream from XCode (v12.4) to Processing (https://processing.org/). My goal is: To draw a simple object in Processing according to my XCode project data.

I need to see value of my variable in the Processing.

int main(int argc, const char * argv[]) {
    // insert code here...
    for (int i=0; i<10; i  )
      std::cout << "How to send value of i to the Processing!\n";
    
    return 0;
}

CodePudding user response:

The assumption is you're using c in Xcode (and not Objective-C, nor Swift).

Every processing sketch inherits the args property (very similar to main's const char * argv[] in c program). You can make use of that to initialise a Processing sketch with options from c .

You could have something like:

int main(int argc, const char * argv[]) {
    system("/path/to/processing-java --sketch-path=/path/to/your/processing/sketch/folder --run 0,1,2,3,4,5,6,7,8,9");
    return 0;
}

(This is oversimplified, you'd have your for loop accumulate ints into a string with a separator character, maybe setup variables for paths to processing-java and the processing sketch)

To clarify, processing-java is a command line utility that ships with Processing. (You can find it in inside the Processing.app folder (via show contents), alongside the processing executable and install it via Tools menu inside Processing). It allows you to easily run a sketch from the command line. Alternatively, you can export an application, however if you're prototyping, the processing-java option might be more practical.

In Processing you'd check if the sketch was launched with arguments, and if so, parse those arguments.

void setup(){
  if(args != null){
    printArray(args);
  }
}

You can use split() to split 0,1,2,3,4,5,6,7,8,9 into individual numbers that can be parsed (via int() for example).

If you have more complex data, you can consider formatting your c output as JSON, then using parseJSONObject() / parseJSONArray().

(If you don't want to split individual values, you can just use spaces with command line arguments: /path/to/processing-java --sketch-path=/path/to/your/processing/sketch/folder --run 0 1 2 3 4 5 6 7 8 9. If you want to send a JSON formatted string from c , be aware you may need to escape " (e.g. system("/path/to/processing-java --sketch-path=/path/to/your/processing/sketch/folder --run {\"myCppData\":[0,1,2]}");)

This would work if you need to launch the processing sketch once and initialise with values from your c program at startup. Outside of the scope of your question, if you need to continously send values from c to Processing, you can look at opening a local socket connection (TCP or UDP) to estabish communication between the two programs. One easy to use protocol is OSC (via UDP). You can use oscpack in raw c and oscp5 in Processing. (Optionally, depending on your setup you can consider openFrameworks which (already has oscpack integrated as ofxOsc and ships with send/receive examples): its ofApp is similar Processing's PApplet (e.g. setup()/draw()/mousePressed(), etc.)

CodePudding user response:

Finally I found the way. Hope it help someone. Share it.

Xcode app ->(127.0.0.1:UDP)-> Processing sketch

Source Links:

Sending string over UDP in C

https://discourse.processing.org/t/receive-udp-packets/19832

Xcode app (C ):

int main(int argc, char const *argv[])
{
    std::string hostname{"127.0.0.1"};
    uint16_t port = 6000;

    int sock = ::socket(AF_INET, SOCK_DGRAM, 0);

    sockaddr_in destination;
    destination.sin_family = AF_INET;
    destination.sin_port = htons(port);
    destination.sin_addr.s_addr = inet_addr(hostname.c_str());
    
    
    
    std::string msg = "Hello world!";
    for(int i=0; i<5; i  ){
    long n_bytes = ::sendto(sock, msg.c_str(), msg.length(), 0, reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
    std::cout << n_bytes << " bytes sent" << std::endl;
    }
        ::close(sock);
    
    return 0;
}

Processing code:

import java.net.*;
import java.io.*;
import java.util.Arrays;

DatagramSocket socket;
DatagramPacket packet;

byte[] buf = new byte[12]; //Set your buffer size as desired

void setup() {
  try {
    socket = new DatagramSocket(6000); // Set your port here
  }
  catch (Exception e) {
    e.printStackTrace(); 
    println(e.getMessage());
  }
}

void draw() {
  try {
    DatagramPacket packet = new DatagramPacket(buf, buf.length);
    socket.receive(packet);
    InetAddress address = packet.getAddress();
    int port = packet.getPort();
    packet = new DatagramPacket(buf, buf.length, address, port);

    //Received as bytes:
    println(Arrays.toString(buf));
    
    //If you wish to receive as String:
    String received = new String(packet.getData(), 0, packet.getLength());
    println(received);
  }
  catch (IOException e) {
    e.printStackTrace(); 
    println(e.getMessage());
  }
}
  • Related