This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
IndustrialLemon's profile picture

Passing information between programs..?

Started by IndustrialLemon, 04 November 2018 - 04:54 AM
IndustrialLemon #1
Posted 04 November 2018 - 05:54 AM
I'd like to get a solid understand on how I could pass a variable between two different programs. For example, taking variable x = 5 and sending it to another program by sending it and running the other program. os.run({}, "other_program.lua").

I did some research and came across this but even after copying it word for word it's not working. I try some of my own experimentation too, and once again I come up short.
Spoiler

function serialize(data, name)
if not fs.exists('/data') then
  fs.makeDir('/data')
end
local f = fs.open('/data/'..name, 'w')
f.write(textutils.serialize(data))
f.close()
end
function unserialize(name)
if fs.exists('/data/'..name) then
  local f = fs.open('/data/'..name, 'r')
  data = textutils.unserialize(f.readAll())
  f.close()
end
return data
end
If you could explain in detail why this isn't working or another solution that works that'd be very helpful. I already understand the textutils.serialize just breaks a table up so that you can actually play with the variables but that's all I really gather.
Lupus590 #2
Posted 04 November 2018 - 10:21 AM
Where are the two programs running?
  • Are they on the same CC computer?
  • If not, are they in the same MC dimention?
  • Are they on the same MC server?
When do they send information to each other?
  • Does one program needs to send data to another when the second one starts?
  • Will both need to send data back and forth to each other throughout the programs?
Bomb Bloke #3
Posted 04 November 2018 - 04:10 PM
os.run({}, "other_program.lua")

Generally you won't want to use os.run(): use shell.run() until you've got a solid understanding of environment tables. If your "other program" wants to make use of the shell table for eg, your current method of launching it will cause a crash.

If you could explain in detail why this isn't working

What does it do? What data are you passing in? What data is it passing out?

I already understand the textutils.serialize just breaks a table up so that you can actually play with the variables but that's all I really gather.

Other way around: it constructs a single string representing the full table content. textutils.unserialise() breaks that string back up into a table.
IndustrialLemon #4
Posted 04 November 2018 - 06:51 PM
os.run({}, "other_program.lua")

Generally you won't want to use os.run(): use shell.run() until you've got a solid understanding of environment tables. If your "other program" wants to make use of the shell table for eg, your current method of launching it will cause a crash.

If you could explain in detail why this isn't working

What does it do? What data are you passing in? What data is it passing out?

I already understand the textutils.serialize just breaks a table up so that you can actually play with the variables but that's all I really gather.

Other way around: it constructs a single string representing the full table content. textutils.unserialise() breaks that string back up into a table.


Could you explain why I should be using shell.run over os.run in greater detail? Is an environment table something I can make use of here?

I'm not sure what it actually does. This program came up as something I could salvage if wanting to take 'data' and make a file to hold it so that I could use the other half of the script to pull that data in another program. Though it doesn't seem to work and I don't understand it enough to mess with it properly.

Basically, I don't care how it's done, but I just want to pass information between two programs. At the moment, only one program is running and when it's finished doing Its job it runs another program that grabs the information from it.

If I end up having to run the two programs at the same time sure I can do that. Just help me do it.
If I have to paste my information into a file and grab it later, I can do that too. Just help me do it.
Aaand, if there's a way to pass the information with a simple friggin command that I'm not aware of by all means shout it to me!
Where are the two programs running?

  • Are they on the same CC computer?
  • If not, are they in the same MC dimention?
  • Are they on the same MC server?
Yes, yes, and yes. Playing singleplayer!

Hope this answered both of your questions so that you guys can help answer mine. Thanks
Lupus590 #5
Posted 04 November 2018 - 09:09 PM
With two programs on one PC you might want to use global variables for exchanging data between them. A better way would be to combine the two into one program (possibly via the parallel API - however restructuring your code may allow you to combine the two programs and not use the API).

You said that the first program starts the second when it finishes, you may want to pass the data as program arguments.
Dog #6
Posted 04 November 2018 - 09:49 PM
It sounds like Lupus590 has you covered - passing the data as arguments when launching the next program is probably the best way to go.

If, however, both programs are running at the same time and you want to pass data between them, then using globals is the simple, straight forward, and probably best approach - however, there is a way to do it without using globals, for whatever it's worth.

Instead of using globals, queue a custom event with the data holding the value to be transferred. It would be a bit more difficult with multiple values but it could be accomplished something like this…

Sending computer

x = 5
y = 7
z = 2
os.queueEvent("customEvent", x, y, z)

Receiving computer

local event, dataX, dataY, dataZ = os.pullEvent()
if event == "customEvent" then
  x = dataX
  y = dataY
  z = dataZ
end

Obviously, it could be further extended by using a tables instead of individual variables.

If the receiving program is event driven, this would be advantageous in that the program could easily determine when values have changed instead of using a timer or other methods. Clearly this is moot if the program doesn't care when values have changed and uses them however they are in whatever state it's in.
Edited on 04 November 2018 - 08:58 PM
Bomb Bloke #7
Posted 05 November 2018 - 04:04 AM
Could you explain why I should be using shell.run over os.run in greater detail? Is an environment table something I can make use of here?

Whenever you declare anything in the global scope, it goes into the environment table.

Normally your environment table would be _G, though in ComputerCraft, the CraftOS shell gives you a different one (which has access to _G's content via a metatable). The regular CC APIs are loaded into _G, and any globals you declare go into the table the shell system made for you.

However, not all "APIs" are in _G: some are "shell-specific", and since you can have more than one instance of the shell running on a system at a time, that means they need to be loaded into script-specific environment tables. The shell table is the most important example.

With all of that in mind, shell.run() starts another script up and configures a regular environment table for it to use (with access to _G and shell and so on), whereas os.run() expects you to figure out the appropriate environment table yourself.

Yeah, you can technically pass values from script to script using an environment table, but it's a messy way to do it. Under CC 1.79 or earlier, it's simply a matter of declaring whatever in the global scope, using shell.run() to launch the next script, and that's it: the variables will be available (… and they'll still be loaded in memory once your scripts end, "polluting" the environment table).

Under CC 1.80, shell.run() gives every script you launch a separate global environment, so global pollution is no longer a thing: you'd need to construct a suitable table and pass it through os.run() instead if you really wanted to work around that.

Though it doesn't seem to work and I don't understand it enough to mess with it properly.

No one can tell you why if you don't show the relevant code. Again: what are you passing in? Show the lines where you call serialize(), and define its parameters! What are you getting out? Print whatever unserialize() is returning!

Aaand, if there's a way to pass the information with a simple friggin command that I'm not aware of by all means shout it to me!

shell.run("whateverScript", "5", "turnip", "astronaught")

local args = {...}

print(args[1])
print(args[2])
print(args[3])

local x = tonumber(args[1])

Whether this is suitable at all depends on whether you're trying to pass simple strings and numbers, but hey. If you want something that's "simple", that fits the bill.