В солидности очевидно, как получить одну строку, возвращаемую функцией. Но я бы хотел, чтобы смарт-контракт возвращал несколько строковых значений. Есть ли способ сделать это?
Есть несколько типов строковых значений, на которые вы можете ссылаться.
bytes1
- bytes32
: фиксированный размер.bytes
или string
: динамический размер.Solidity поддерживает функции с несколькими возвращаемыми значениями.
contract MultiReturner {
function getData() constant returns (bytes32, bytes32) {
bytes32 a = "abcd";
bytes32 b = "wxyz";
return (a, b);
}
function getDynamicData() constant returns (bytes, bytes) {
bytes a;
a.push('a');
a.push('b');
a.push('c');
bytes b;
b.push('x');
b.push('y');
b.push('z');
return (a, b);
}
}
Вы можете сделать то же самое с bytes
или string
, но с тем ограничением, что Solidity не поддерживает возврат значений динамического размера в другие функции. Это означает, что вы сможете использовать getData
функцию из другого контракта и получить возвращаемые значения, но не сможете получить возвращаемые значения getDynamicData
из контракта.
contract UsesMultiReturner {
function doIt() {
mr = MultiReturner(0x1234);
// this will work
var (a, b) = mr.getData();
// this won't work
var (a, b) = mr.getDynamicData();
}
}
Однако вы можете получить возвращаемые значения как из, так и getData
из -за пределов блокчейна.getDynamicData
call
Вы можете использовать библиотеку Seriality . Seriality — это библиотека для очень эффективной сериализации и десериализации всех типов Solidity, которая в основном написана на Solidity-Assembly.
1- С помощью Seriality вы можете легко сериализовать и десериализовать свои переменные, структуры, массивы, кортежи... и передавать их через контракты и библиотеки.
2- Вы можете отделить свой контракт от библиотек, сериализовав параметры в массив байтов.
3- Его также можно использовать в качестве альтернативы протоколу RLP в Solidity.
Вот пример:
pragma solidity ^0.4.16;
import "./Seriality.sol";
contract StringsReturn is Seriality {
function stringCaller() public returns( string memory out1,
string memory out2,
string memory out3,
string memory out4,
string memory out5)
{
bytes memory buffer = new bytes(320);
uint offset = stringCallee(buffer);
//deserializing
out1 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out1));
offset -= sizeOfString(out1);
out2 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out2));
offset -= sizeOfString(out2);
out3 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out3));
offset -= sizeOfString(out3);
out4 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out4));
offset -= sizeOfString(out4);
out5 = new string (getStringSize(offset, buffer));
bytesToString(offset, buffer, bytes(out5));
}
function stringCallee(bytes memory buffer) public returns (uint buffer_size) {
string memory out1 = new string(32);
string memory out2 = new string(32);
string memory out3 = new string(32);
string memory out4 = new string(32);
string memory out5 = new string(32);
out1 = "Come on baby lets dance!";
out2 = "May I buy you a drink?";
out3 = "I am an itinerant programmer";
out4 = "Inam javab lashi!";
out5 = "Bia inja dahan service";
// Serializing
buffer_size = sizeOfString(out5) +
sizeOfString(out4) +
sizeOfString(out3) +
sizeOfString(out2) +
sizeOfString(out1);
uint offset = buffer_size;
stringToBytes(offset, bytes(out1), buffer);
offset -= sizeOfString(out1);
stringToBytes(offset, bytes(out2), buffer);
offset -= sizeOfString(out2);
stringToBytes(offset, bytes(out3), buffer);
offset -= sizeOfString(out3);
stringToBytes(offset, bytes(out4), buffer);
offset -= sizeOfString(out4);
stringToBytes(offset, bytes(out5), buffer);
return buffer_size;
}
}
Это вывод stringCaller()
"0": "string: out1 Come on baby lets dance!",
"1": "string: out2 May I buy you a drink?",
"2": "string: out3 I am an itinerant programmer",
"3": "string: out4 Inam javab lashi!",
"4": "string: out5 Bia inja dahan service"
А вот буфер:
42696120696e6a6120646168616e207365727669636500000000000000000000
0000000000000000000000000000000000000000000000000000000000000016
496e616d206a61766162206c6173686921000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000011
4920616d20616e206974696e6572616e742070726f6772616d6d657200000000
000000000000000000000000000000000000000000000000000000000000001c
4d617920492062757920796f752061206472696e6b3f00000000000000000000
0000000000000000000000000000000000000000000000000000000000000016
436f6d65206f6e2062616279206c6574732064616e6365210000000000000000
0000000000000000000000000000000000000000000000000000000000000018
альпер
bytes32
, должны ли мы привести типvar
кbytes32
?@Piper Merriam.Пайпер Мерриам
var
может использоваться для делегирования выбора соответствующего типа компилятору.a
иb
будет установлено какbytes32
компилятор, так как компилятор знает, чтоmr.getData()
вернет тип(bytes32, bytes32)
ДжонАллен
var
теперь устарело. Есть ли обновление о том, как вернуть несколько значений с помощью0.4.21
?цифровой осел