1

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;
}
OverFF
  • 31
  • 3

2 Answers2

2

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());
  }
}
OverFF
  • 31
  • 3
  • Nice one(+1).Instead of using OSC you went for UDP directly. UDP is pretty fast, but bare in mind as opposed to the TCP protocol you have no guarantee all UDP messages will be received and that will be received in the same order they're sent. In your case, using `localhost` and simple short messages, it might not affect you at all, but something to keep in mind perhaps for larger projects with more machines on larger networks. (TCP on the other hand does guarantee each message sent is received once the server/client sockets connect and well as the order, but the packets are chunkier).Goodluck! – George Profenza Nov 14 '22 at 00:27
1

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.)

George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • Thanks for your rapid answer. I will research it. And yes, I am going to continuously send values from Xcode(C++) to the Processing. – OverFF Nov 13 '22 at 11:32
  • Then the closing part of my answer cover that. I would test something like this: 1. setup openFrameworks with Code (should be download zip, unzip). 2. run projectGenerator and import `examples/communication/oscSenderExample`, generate the XCode project and compile (first time will be slower as it compiles openFrameworksLib, after that it's just your ofApp). 3. Install oscp5 in Processing via **Sketch > Import Library... > Add Library...** and type oscp5. After the library is installed, open **Examples (CMD+Shift+O) > Contributed Libraries > oscP5 > basics** and change port from 12000 to 12345 – George Profenza Nov 13 '22 at 12:40
  • ...after that , as you can see in [oscSenderExample](https://github.com/openframeworks/openFrameworks/blob/master/examples/communication/oscSenderExample/src/ofApp.cpp), you need to parse the oscMessage with address "/mouse/position" whith 2 float arguments (normalised x and y coordinates), (e.g. if you get those 2 arguments and mutiply the first to sketch width and the other to sketch height you should see the same mouse motion from oF in your Processing sketch). Goodluck! – George Profenza Nov 13 '22 at 12:43