Now when I understand how the code works, I would like to translate it to C++.
The original Python code:
def recv_all_until(s, crlf):
data = ""
while data[-len(crlf):] != crlf:
data += s.recv(1)
return data
Here's what I tried:
std::string recv_all_until(int socket, std::string crlf)
{
std::string data = "";
char buffer[1];
memset(buffer, 0, 1);
while(data.substr(data.length()-2, data.length()) != crlf)
{
if ((recv(socket, buffer, 1, 0)) == 0)
{
if (errno != 0)
{
close(socket);
perror("recv");
exit(1);
}
}
data = data + std::string(buffer);
memset(buffer, 0, 1);
}
return data;
}
But it shows:
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
I understand that the problem is inside the while loop since at first the data string is empty. So how to improve this to make it work the same as it works in Python? Thank you.
You have the problem in the first iteration of your while loop:
Since the data is an empty string, data.length() is equal to 0, and thus you're calling data.substr(-2, 0).
To fix this, you need to add a check for the line length to the while statement.
Also, there's a method of finding such mistakes faster than writing a stackoverflow question about it. Consider reading this article.
If we first change your Python code a bit:
def recv_all_until(s, crlf):
data = ""
while not data.endswith(crlf):
data += s.recv(1)
return data
What we need to do in C++ becomes much clearer:
bool ends_with(const std::string& str, const std::string& suffix)
{
return str.size() >= suffix.size() &&
std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
}
std::string recv_all_until(int socket, const std::string& crlf)
{
std::string data = "";
char buffer[1];
memset(buffer, 0, 1);
while (!ends_with(data, crlf))
{
if ((recv(socket, buffer, 1, 0)) == 0)
{
if (errno != 0)
{
close(socket);
perror("recv");
exit(1);
}
}
data = data + std::string(buffer);
memset(buffer, 0, 1);
}
return data;
}
Related
I am writing a program that requires the starting of a python script before the rest of the java code runs. However, I cannot find a solution to my issues. I would appreciate if someone could suggest a solution to the problem I am facing.
Code (I need help on the part under the comment "start python"):
import java.io.IOException;
//makes it easier for user to
//select game/start python
public class gameselect {
public static void main(String args[]) throws IOException {
//start python
try {
String cmd = "python ngramcount.py";
Process process = Runtime.getRuntime().exec(cmd);
process.getInputStream();
}
catch (IOException e) {
e.printStackTrace();
}
//select game
try {
Scanner in = new Scanner (System.in);
game1 g = new game1();
game2 f = new game2();
int choice = 0;
System.out.println("Welcome to TranslateGame!");
System.out.println("Type 1 for game1 (words) or 2 for game2 (phrases)");
while (choice != 1 && choice != 2) {
choice = in.nextInt();
if (choice != 1 && choice != 2) {
System.out.println("No game associated with that number.");
}
}
if (choice == 1) {
g.game1();
}
else if (choice == 2) {
f.game2();
}
}
catch(IOException e) {
System.out.println("No.");
}
}
}
Here is some code that you might be able to get to work. I also commented it and provided some reference links to help you understand what the code is doing.
public static void main(String[] args) throws IOException {
// I'm using the absolute path for my example.
String fileName = "C:\\Users\\yourname\\Desktop\\testing.py";
// Creates a ProcessBuilder
// doc: https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html
ProcessBuilder pb = new ProcessBuilder("python", fileName);
pb.redirectErrorStream(true); // redirect error stream to a standard output stream
Process process = pb.start(); // Used to start the process
// Reads the output stream of the process.
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line; // this will be used to read the output line by line. Helpful in troubleshooting.
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
This question is an evolution of this: Issue returning header byte from Python to Unity
Now the issue about header byte is solved, but I have a problem during the loop.
The data incoming good but after "n" times the loop break because receive a json string with an entire structure of data with open/close bracket PLUS the next structure of data with open bracket, some data and in the "image:" some data and many of the "\0" and unless the close bracket.. And the json parser obviously breaks. Why and what can I do? Thanks
Below the code revised:
IEnumerator Client()
{
while (!IsConnected(client))
{
try
{
client = new TcpClient(host, port);
s = client.GetStream();
byte[] byteBuffer = Encoding.UTF8.GetBytes("Connected to client");
s.Write(byteBuffer, 0, byteBuffer.Length);
while (true)
{
if (s.DataAvailable)
{
while (s.DataAvailable)
{
var header = new byte[4];
s.Read(header, 0, header.Length);
var fileSize = BitConverter.ToUInt32(header,0);
StringBuilder myCompleteMessage = new StringBuilder();
MemoryStream ms = new MemoryStream();
int increment = 0;
while (ms.Length < fileSize)
{
byte[] dataReceived = new byte[fileSize];
increment = s.Read(dataReceived, 0, dataReceived.Length);
ms.Write(dataReceived.Take(increment).ToArray(), 0, increment);
}
myCompleteMessage.AppendFormat("{0}", Encoding.UTF8.GetString(ms.GetBuffer()));
JSONNode data = JSONNode.Parse(myCompleteMessage.ToString());
....
// Do work with myCompleteMessage
yield return null;
}
}
}
}
}
}
I don't have your Unity environment here, so I can't have tested this.
Something like a loop (likely run in a coroutine or something that doesn't block Unity's default handling) like this should be enough to handle a stream of messages of the shape we established before (a 4-byte header signifying the message length, followed by that many bytes of JSON).
while (!IsConnected(client))
{
try
{
client = new TcpClient(host, port);
s = client.GetStream();
while (true)
{
var data = ReadPacket(s);
// Do work with data
}
}
}
ReadPacket should be something like
JSONNode ReadPacket(Stream s)
{
var buffer = new byte[131072];
// Read 4 bytes (we will assume we can always read that much)
var n = s.Read(buffer, 0, 4);
if(n < 4) throw new Exception("short read");
var fileSize = BitConverter.ToUInt32(buffer, 0);
Debug.Print("Reading a blob of length", fileSize);
// Memory stream to accumulate the reads into.
var ms = new MemoryStream();
while (ms.Length < fileSize)
{
// Figure out how much we can read -- if we're near the end,
// don't overread.
var maxRead = Math.Min(buffer.Length, fileSize - ms.Length);
var increment = s.Read(buffer, 0, maxRead);
// ... and write them into the stream.
ms.Write(buffer, 0, increment);
Debug.Print("Read", ms.Length, "of", fileSize);
}
// Decode the bytes to UTF-8 and parse.
return JSONNode.Parse(Encoding.UTF8.GetString(ms.GetBuffer()));
}
This code coverts an Array Buffer to a String and vice versa
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
I think Python bytearray() can do the job.
u can refer this page for more info: https://www.programiz.com/python-programming/methods/built-in/bytearray
I'm using the below lines of code to extract the pixel array from a camera at every frame, saving it as jpg and then running a python process on the jpg. Although it works, it is incredibly slow. The bottleneck seems to be reading the pixels in unity. The python process itself only lasts 0.02 seconds.
Can anyone suggest relatively easy ways I can speed up this process?
I've seen this , but it's too high-level for me to understand how to adapt it to my use-case.
public override void Initialize()
{
renderTexture = new RenderTexture(84, 84, 24);
rawByteData = new byte[84 * 84 * bytesPerPixel];
texture2D = new Texture2D(84, 84, TextureFormat.RGB24, false);
rect = new Rect(0, 0, 84, 84);
cam.targetTexture = renderTexture;
}
private List<float> run_cmd()
{
// Setup a camera, texture and render texture
cam.targetTexture = renderTexture;
cam.Render();
// Read pixels to texture
RenderTexture.active = renderTexture;
texture2D.ReadPixels(rect, 0, 0);
rawByteData = ImageConversion.EncodeToJPG(texture2D);
// Assign random temporary filename to jpg
string fileName = "/media/home/tmp/" + Guid.NewGuid().ToString() + ".jpg";
File.WriteAllBytes(fileName, rawByteData); // Requires System.IO
// Start Python process
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "/media/home/path/to/python/exe";
start.Arguments = string.Format(
"/media/home/path/to/pythonfile.py photo {0}", fileName);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
string stdout;
using(Process process = Process.Start(start))
{
using(StreamReader reader = process.StandardOutput)
{
stdout = reader.ReadToEnd();
}
}
string[] tokens = stdout.Split(',');
List<float> result = tokens.Select(x => float.Parse(x)).ToList();
System.IO.File.Delete(fileName);
return result;
}
In Unity 2018.1 was added a new system for async read data from GPU - https://docs.unity3d.com/ScriptReference/Rendering.AsyncGPUReadback.html, and in this not necessary use camera for getting array of textures, I wrote a simple example which good work and pretty fast:
using System.Collections;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
public class CameraTextureTest : MonoBehaviour
{
private GraphicsFormat format;
private int frameIndex = 0;
IEnumerator Start()
{
yield return new WaitForSeconds(1);
while (true)
{
yield return new WaitForSeconds(0.032f);
yield return new WaitForEndOfFrame();
var rt = RenderTexture.GetTemporary(Screen.width, Screen.height, 32);
format = rt.graphicsFormat;
ScreenCapture.CaptureScreenshotIntoRenderTexture(rt);
AsyncGPUReadback.Request(rt, 0, TextureFormat.RGBA32, OnCompleteReadback);
RenderTexture.ReleaseTemporary(rt);
}
}
void OnCompleteReadback(AsyncGPUReadbackRequest request)
{
if (request.hasError)
{
Debug.Log("GPU readback error detected.");
return;
}
byte[] array = request.GetData<byte>().ToArray();
Task.Run(() =>
{
File.WriteAllBytes($"D:/Screenshots/Screenshot{frameIndex}.png",ImageConversion.EncodeArrayToPNG(array, format, (uint) Screen.width, (uint) Screen.height));
});
frameIndex++;
}
}
You can adapt this example to your task.
I defined a variable m_index with initial value -1. I increase this variable in the first for loop and then use the increased value in second for loop.
The problem is when I put the print command at the end of first loop, the value of m_index is correct but when I comment the print command, the value of m_index remains -1.
I would appreciate any help. The code is written in C language using python API and my platform is linux ubuntu 64bit.
static PyObject *get_outside_members(PyArrayObject *AA, PyArrayObject *bb, npy_int AA_index)
{
npy_intp m_index=-1, fp_index=-1, o_index=0, i=0;
npy_double distance=0.0, max_distance=0;
PyArrayObject *tmembers, *tfurthest_points;
npy_intp dims[1];
PyObject *r;
//---------------------------------------------------------
dims[0]=outs_N;
tmembers=(PyArrayObject *)PyArray_SimpleNew(1,dims,NPY_INT);
if(tmembers==NULL)
{
PyErr_SetString(PyExc_ValueError,"Could not create tmembers array");
return NULL;
}
distances=(PyArrayObject *)PyArray_SimpleNew(1,dims,NPY_DOUBLE);
if(distances==NULL)
{
PyErr_SetString(PyExc_ValueError,"Could not create distances array");
return NULL;
}
tfurthest_points=(PyArrayObject *)PyArray_SimpleNew(1,dims,NPY_INT);
if(tfurthest_points==NULL)
{
PyErr_SetString(PyExc_ValueError,"Could not create tfurthest_points array");
return NULL;
}
dims[0]=1;
furthest_dist=(PyArrayObject *)PyArray_SimpleNew(1,dims,NPY_DOUBLE);
if(furthest_dist==NULL)
{
PyErr_SetString(PyExc_ValueError,"Could not create furthest_dist array");
return NULL;
}
//---------------------------------------------------------
for(i=0;i<outs_N;i++)
{
o_index=outsides(i);
distance = distpalne(AA,bb,AA_index,o_index);
if(i == 0)
max_distance = distance;
else if(distance > max_distance)
max_distance = distance;
if(distance >= 0)
{
m_index++;
tmembers(m_index)=o_index;
distances(m_index)=distance;
}
}
//printf("m_index=%d\n",m_index);
for(i=0;i<=m_index;i++)
{
if(distances(i) == max_distance)
{
fp_index++;
tfurthest_points(fp_index)=tmembers(i);
}
}
PyArray_Return(tmembers);
}
I am very sure this does not have anything to do with the printf. printf get's the variables value by value and therefore cannot change anything. If I were you, I would check that again after some time has passed.
In addition, when you are debugging using print statements, always add fflush(stdout); after every print statement to make sure that the value is immediately printed. As an alternative, you could print to stderr which is flushed automatically:
fprintf(stderr, "prints directly");
Another thing I would check is, that you do not have any memory-errors. You can use Valgrind for that.