Encode the program name together with all arguments as one big string, discarding all type safety, spawn the process of your favorite shell, let that shell process the string in order to spawn one or multiple processes, in each process have the standard library process the arguments into an array called argv, and have your average process call out to yet another library to parse these string argument strings into flags and parameters, and prints a not standarized, potentially localized string if an error occurs, and if the error is fatal exits with a semi-standarized return code. The calling program tries to make sense of the output of the called program, often by fuzzy matching against known output.
That's the standard way how it's done since the beginning of Unix. Some APIs skip the shell, but that's a minor detail in all this. If this sounds simple and like the obviously best solution, then congratulations. The windows developers disagree and tried (and continue to try) to find a better way. They mostly failed so far, but I think we should thank them for at least trying to innovate.