Extract array of bytes from GVariant - gtk3

I want to pass an array of bytes such as [1,2,3,4,5] between processes using DBus. I understand, that I can use the BYTE type to declare an array of bytes (i.e., ay) and then use GVariant to store and retrieve the values? How can I create a GVariant that can hold this data and how can I get it back out?

A GVariant can be created using g_variant_new_from_data. The first two arguments are the type of the variant (ay) as well as a pointer to an array of bytes with the inputs for the variant.
guint8 input[] = { 1, 2, 3, 4, 5 };
GVariant * variant;
variant = g_variant_new_from_data(G_VARIANT_TYPE ("ay"),
input,
G_N_ELEMENTS(input),
TRUE,
NULL,
NULL);
To get the data back out we can use g_variant_get_fixed_array.
guint8 * array = NULL;
gsize n_elements;
array = g_variant_get_fixed_array (variant,
&n_elements,
sizeof(guint8));
g_assert (n_elements == 5);
g_assert (array != NULL);

Related

Swift array address is not same as &array[0]

Document said:
An in-out expression that contains a mutable variable, property, or subscript reference of type Type, which is passed as a pointer to the address of the left-hand side identifier.
A [Type] value, which is passed as a pointer to the start of the array.
But when I run the following code :
func print<Type>(unsafePointer pointer: UnsafePointer<Type>) {
print("\(pointer) ==> \(pointer.pointee) : \(Type.self)")
}
var array = [1, 2, 3, 4]
print(unsafePointer: array)
print(unsafePointer: &array[0])
I get
0x0000000104204240 ==> 1 : Int
0x00007ffeefbff440 ==> 1 : Int
Why their addresses are different?
Here
print(unsafePointer: array)
a pointer to the first element of the array storage is passed to the function. And here
print(unsafePointer: &array[0])
the subscript operator is called on the array (returning an Int) and the address of that (temporary) integer is passed to the function, not the address where the original array element is stored.
That becomes more obvious if you call the functions twice:
var array = [1, 2, 3, 4]
print(unsafePointer: array) // 0x00007ffeefbff2e0
print(unsafePointer: array) // 0x00007ffeefbff2e0, same as previous address
print(unsafePointer: &array[0]) // 0x00007ffeefbff320
print(unsafePointer: &array[0]) // 0x00007ffeefbff340, different from previous address
In addition, passing an in-out expression to a function can make a temporary copy, see for example Swift: always copies on inout?.
Arrays in Swift have value semantics, not the reference semantics of arrays in C or Objective-C. The reason you're seeing different addresses (and addresses at all) is that every time you pass the array as a parameter, you're actually telling Swift to bridge your Array struct to an instance of NSArray.

Twincat 3: How to convert 4 HEX array to Float?

we are receiving (via UDP datagram) a float value codified by 4 bytes hex array.
We need to convert from 4 hex bytes to a float.
udp_data[0] = 'BE';
udp_data[1] = '7A';
udp_data[2] = 'E0';
udp_data[3] = 'F4';
In the given example, the correct equivalence, after transformation, udp_data is equivalent to -0.24499:
What is the optimal conversion in Twincat 3 PLC? maybe some library? We need to perform 52 transformation at once of this type.
I attached an example with an example taken from an online calculator:
Thanks!!
You can use a UNION type, which will at the same address hold a byte array (like the one you get from your UDP communication) and the real var which you want to convert to.
When you change the byte array, the real automatically reflects it. The conversion works the other way around also, in fact.
TYPE U_Convert :
UNION
arrUDP_Data: ARRAY [0 .. 3] OF BYTE; // Array must start with LSB
rReal : REAL;
END_UNION
END_TYPE
In MAIN you can declare the following var.
VAR
uConvert: U_Convert;
fValue : REAL;
END_VAR
And in the body of MAIN, update the byte array to requested values.
// Here we update the byte array
uConvert.arrUDP_Data[0] := 16#F4; // LSB
uConvert.arrUDP_Data[1] := 16#E0;
uConvert.arrUDP_Data[2] := 16#7A;
uConvert.arrUDP_Data[3] := 16#BE; // MSB
// Here we 'use' the converted value
fValue := uConvert.rReal;
I assume you have an array of bytes.
Header (put this in own function block if you want):
PROGRAM MAIN
VAR
aByteArray : ARRAY[1..4] OF BYTE := [16#F4, 16#E0, 16#7A, 16#BE];
pt : POINTER TO REAL;
fRealValue : REAL;
END_VAR
Body:
pt := ADR(aByteArray);
fRealValue := pt^;
Will give you the desired result:

Using Swift to reference an external C function call that uses pointers

Being new to Xcode, I am trying to make use of an external C call that use pointers, and I’m having difficulty finding a way to reference them in Swift. The original call in C is defined as:
int32 FAR PASCAL swe_calc(double tjd, int ipl, int32 iflag, double *xx, char *serr)
where xx is a pointer to an array of 6 Doubles and serr is a pointer to any error message(s)
Swift sees it as:
int32 swe_calc(tjd: Double, ipl: Int32, iflag: int32, xx: UnsafeMutablePointer<Double>, serr: UnsafeMutablePointer<Int8>)
(from: https://github.com/dwlnetnl/SwissEphemeris/tree/master/SwissEphemeris)
The closest thing I’ve tried that even comes close is:
var serr : UnsafeMutablePointer<Int8> = nil; // returns any error messages from the call
var x = [Double](count: 6, repeatedValue: 0); // array of 6 doubles returned from the call
var xx : UnsafeMutablePointer<Double> ;
xx = &x
swe_calc(2436647.0003794227, 4, 258, xx, serr)
println("xx = \(x[0]), \(x[1]), \(x[2]), \(x[3]), \(x[4]), \(x[5]), errors (if any)=\(serr)")
The line xx=&x gives the error
Cannot assign a value of type input[(Double)] to a value of type ‘UnsafeMutablePointer’
I need a way to get/reference/use the values returned from xx into an array of 6 doubles, and serr should definitely not be an Int8, but a string instead. (I can get the other Java and C# versions to work, but Swift has me stumped.)
How can I make the swe_calc call to give it what it needs, and get out what I need?
You were close. Both UnsafeMutablePointer parameters need an
array of the appropriate type passed as "inout argument" with &:
var x = [Double](count: 6, repeatedValue: 0);
var serr = [Int8](count: 1024, repeatedValue: 0)
let result = swe_calc(2436647.0003794227, 4, 258, &x, &serr)
Of course the arrays must be allocated large enough as expected by
the C function.
If that function puts a NUL-terminated error string into the buffer
pointed to by serr then you can convert it to a Swift string with:
let errorString = String.fromCString(&serr)

Convert a slice to native (endianness) integer

I have a slice of bytes (which I know that are an integer saved as little endian) and I want to convert them to an integer.
When I had a static-sized array it was no problem, but now I have a slice (ubyte[]).
Is it possible to still convert it to an integer, e.g. in this fashion?
ubyte[] bytes = ...;
uint native = littleEndianSliceToNative!uint(bytes);
Taking further what Adam has written, you can write a simple function like
T sliceToNative(T)(ubyte[] slice) if(isNumeric!T) {
const uint s = T.sizeof,
l = min(cast(uint)s, slice.length);
ubyte[s] padded;
padded[0 .. l] = slice[0 .. l];
return littleEndianToNative!T(padded);
}
You could even make the littleEndianToNative a generic type too so you mirror all the operations on arrays for slices.
Just slice the slice explicitly to the appropriate size:
import std.bitmanip;
void main() {
ushort i = 12345;
ubyte[2] swappedI = nativeToLittleEndian(i);
ubyte[] slice = swappedI;
alias Target = ushort; // make this a template param for a generic function
assert(i == littleEndianToNative!Target(slice[0..Target.sizeof])); // the [0..Target.sizeof]
}
That should work for any size needed.

How to Assign a single value to whole NSMutableArray?

I have an mutable array of say 20 objects. And it has values like #"TRUE",#"FALSE",#"TRUE"...
Now I want to reset the all values of array to #"FALSE". Means array having all values as #"FALSE" (20 times).
I know how to add, insert at index... But I want to know that How can I set whole array value to #"FALSE" in a sing line ??? `without using loop and replace object at index... ?
For example : is it possible
thArray = [[NSMutableArray alloc] initWithCapacity:20];
theArray = #"FALSE" ;
Thanks...
Can you use a C array? If so, you can use {0, 1} as C-equivalents of {FALSE, TRUE}, initializing a C array with:
unsigned short int cArray[20] = {0};
or:
static unsigned short int cArray[20]; /* all values are zeroes, or FALSEs */
This might be more efficient, instead of using an array of static NSString * const elements like you're doing now. Testing whether two integers are equivalent is usually faster than testing lexicographical equivalence of two strings, where your program will have to compare each string character by character.
To reset the contents of the array, you can use the C function memset():
memset(cArray, 0, 20*sizeof(unsigned short int)); /* set all values of cArray to 0 */
If you need a dynamically-sized array, use a pointer with calloc() and reset it with memset() as previously described. Just remember to free() the pointer afterwards, so that you don't get a memory leak:
unsigned short int *cArray = NULL;
size_t cArrayLength = 20; /* can be passed in as a value from another method, etc. */
cArray = calloc(cArrayLength, sizeof(unsigned short int)); /* values are initialized to 0 */
if (cArray) {
/* use cArray... */
*(cArray + 8) = 1; /* e.g., set ninth element with the value of 1 */
/* we don't need cArray any longer, so we free it */
free(cArray);
}
else
/* error */
If you must use Objective-C with NSString * or NSNumber * instances in an NSArray or NSMutableArray, there is no ready-made method for initialization and you'll need to use a loop or copy a pre-existing array, as described in Justin's answer. He is also correct that a method for creating and populating the array is a good idea, if you want to go in this direction.
If those were mutable strings inside the array you could do this in just one line:
[theArray makeObjectsPerformSelector:#selector(setString:) withObject:#"FALSE"];
Here's one way:
NSArray * initialized = ...array with fifty #"FALSE" values...;
NSMutableArray * a = [initialized mutableCopy];
... mutate a ...
[a setArray:initialized];
If you are actually dealing with bool values, C scalars will be faster (see Alex's answer).
Another alternative would be a CFMutableBitVector.
Finally, this would also be a good case for creating a function.
1) Either this
2) Or this
Otherwise without a loop there is no way.
only way i know is
for(int i = 0;i<[theArray count];i++)
{[theArray replaceObjectAtIndex:i withObject:#"FALSE"];}