1

I've written a large-ish program in Python, which I need to talk to a smaller C# script. (I realise that getting Python and C# to talk to each other is not an ideal state of affairs, but I'm forced to do this by a piece of hardware, which demands a C# script.) What I want to achieve in particular - the motivation behind this question - is that I want to know when a specific caught exception occurs in the C# script.

I've been trying to achieve the above by getting my Python program to look at the C# script's return code. The problem I've been having is that, if I tell C# to give a return code x, my OS will receive a return code y and Python will receive a return code z. While a given x always seems to correspond to a specific y and a specific z, I'm having difficulty deciphering the relationship between the three; they should be the same.

Here are the specifics of my setup:

  • My version of Python is Python 3.
  • My OS is Ubuntu 20.04.
  • I'm using Mono to compile and run my C# script.

And here's a minimal working example of the sort of thing I'm talking about:

This is a tiny C# script:

namespace ConsoleApplication1
{
    class Script
    {
        const int ramanujansNumber = 1729;

        bool Run()
        {
            return false;
        }

        static int Main(string[] args)
        {
            Script program = new Script();
            if(program.Run()) return 0;
            else return ramanujansNumber;
        }
    }
}

If I compile this using mcs Script.cs, run it using mono Script.exe and then run echo $?, it prints 193. If, on the other hand, I run this Python script:

import os

result = os.system("mono Script.exe")
print(result)

it prints 49408. What is the relationship between these three numbers: 1729, 193, 49408? Can I predict the return code that Python will receive if I know what the C# script will return?

Note: I've tried using Environment.Exit(code) in the C# script instead of having Main return an integer. I ran into exactly the same problem.

Tom Hosker
  • 526
  • 2
  • 17

1 Answers1

3

With os.system the documentation explicitly states that the result is in the same format as for the os.wait, i.e.:

a 16-bit number, whose low byte is the signal number that killed the process, and whose high byte is the exit status (if the signal number is zero); the high bit of the low byte is set if a core file was produced.

So in your case it looks like:

>>> 193<<8
49408

You might want to change that part to using subprocess, e.g. as in the answer to this question

UPD: As for the mono return code, it looks like only the lower byte of it is used (i.e. it is expected to be between 0 and 255). At least:

>>> 1729 & 255
193
Leo K
  • 182
  • 4
  • Thank you for this. If you could give me a bit more explanation regarding `>>> 193<<8 // 49408`, I'll award you the bounty as soon as SO will allow me to do so. (While I still don't understand `>>> 1729 & 255 // 193`, I do get that 193 = 1729 mod 256, which I think amounts to the same thing.) – Tom Hosker Sep 16 '20 at 14:12
  • 2
    Sure! `<<` is binary shift left operator, it takes the number and shifts its binary representation to the left by the given number of bits (8 in this case). The return code (exit status) of the command executed by the `os.system` call in your example is 193. Binary representation of that number is `0b11000001`, which in 16-bit form would like like `0b0000000011000001`. Now if you take that number and move it's bits to the left one-by-one 8 times, you'll get `0b1100000100000000`, which is 49408. So as the doc states, the resulting 16-bit number consists of two 8-bit numbers glued together – Leo K Sep 16 '20 at 14:28
  • Thanks! SO says that I have to wait another 18 hours to award the bounty, so expect it around then. – Tom Hosker Sep 16 '20 at 14:36
  • 2
    As for the `&`, it's bitwise `and` operator, so it's application to the two numbers implies taking binary representations of both numbers, and applying `and` operator to every pair of bits with the same order of significance. In this case 16-bit binary representation of 1729 is `0b0000011011000001`, and 16-bit binary representation of 255 is `0b0000000011111111` (i.e. the lowest 8 bits all having ones, and the highest 8 bits all having zeros), so by applying `&` to any number with 255 as one of the operands, we'll select the lowest 8 bits out of that number. – Leo K Sep 16 '20 at 14:38
  • > SO says that I have to wait another 18 hours to award the bounty, so expect it around then. Gotcha, thank you! :) – Leo K Sep 16 '20 at 14:39
  • Better late than never! – Tom Hosker Sep 20 '20 at 18:51
  • Indeed :) Thanks! – Leo K Sep 20 '20 at 19:09