If I declare a struct A and use that in another struct B. Like struct B { struct A; int len ; } and then I allocate memory for struct B, do I still need to allocate memory for struct A separately ?
What if I use struct *A inside ?
If struct A is embedded into struct B:
struct B {struct A a; int len;}
then you need to allocate memory only for struct B.
If struct B has a pointer to struct A:
struct B {struct A* a; int len;}
then you should allocate both structs, and assign pointer to allocated struct A to field a.
Related
struct JSONAPIResponse<D: Decodable, M: Decodable>: Decodable {
let data: D
let meta: M?
}
I have struct which takes 2 generic types. But 2nd type(M) should be optional. I mean that I want to use this block of code without error:
JSONAPIResponse<DatumEntity>
But now should use pattern:
JSONAPIResponse<DatumEntity, MetaEntity>
So question, how to refactor JSONAPIResponse struct, after that I can use JSONAPIResponse code without error
Let's say I have a function defined in Rust, which looks like this:
#[no_mangle]
pub unsafe extern "C" fn do_something(
my_value: *mut MyStruct,
some_param: c_uint,
content: *mut *mut u8,
length: *mut c_uint,
capacity: *mut c_uint,
) -> *mut MyStruct {
// Do something and obtain an `ffi_result`...
let heap_data = ffi_result.as_mut_ptr();
// These values are passed as "out" parameters.
*length = ffi_result.len() as c_uint;
*capacity = ffi_result.capacity() as c_uint;
*content = heap_data;
// We intentionally "leak" this data to the heap.
// The caller is responsible for cleaning it up by calling another function.
std::mem::forget(ffi_result);
std::boxed::Box::into_raw(value_of_type_my_struct)
}
It takes in a pointer to a struct, a simple integer parameter, several out parameters that can later be used to create an Array and it returns a pointer to a struct.
Now I compile the rust library into a static library for the target aarch64-apple-ios. I set up a XCode project, add the static library as a dependency as explained here with an "Objective-C Bridging Header" where I import the following header file
#ifndef libmy_project_h
#define libmy_project_h
#include <stdint.h>
struct myStruct;
struct myStruct *do_something(struct myStruct *state, int someParam, char **content, int *length, int *capacity);
#endif
Up until this point everything seems to work fine and I have already successfully used this procedure for a whole bunch of other functions. However in this special case I can not figure out how to call this function from swift. I need to call the function from swift and pass content, length and capacity as out parameters so that I can later use the pointers to create an Array in Swift like so.
This is what I tried so far:
var content = UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>(UnsafeMutablePointer(bitPattern: 0))
var length = UnsafeMutablePointer<Int32>(bitPattern: 0)
var capacity = UnsafeMutablePointer<Int32>(bitPattern: 0)
let my_struct = do_something(my_struct, Int32(some_param), content, length, capacity)
let buffer = UnsafeRawBufferPointer(start: content?.pointee, count: Int(length!.pointee))
var data = Array(repeating: UInt8(0), count: Int(length!.pointee))
data.withUnsafeMutableBytes { arrayPtr in
arrayPtr.copyBytes(from: buffer)
}
However now when I execute this swift snippet, I get an EXC_BAD_ACCESS error, which I think occurs because the pointers I manually created do not belong to the adress space of my application. How can I create pointers that I can use as out parameters?
P.S. For reference here is the same interop code in C#:
[DllImport("my_dll")]
private static extern IntPtr do_something(IntPtr state, uint someParam, out IntPtr content, out uint length, out uint capacity);
Which can be called like so:
IntPtr contentPointer;
uint length, capacity;
IntPtr my_struct = do_something(state, myParam, out contentPointer, out length, out capacity);
byte[] rawContent = new byte[length];
Marshal.Copy(contentPointer, rawContent, 0, (int)length);
// Free the data owned by rust with another FFI call:
free_do_something_result(contentPointer, length, capacity);
var length = UnsafeMutablePointer<Int32>(bitPattern: 0)
You need to pass storage for your out-parameters. This is defining a null pointer. When Rust tries to write the result to address 0, it crashes, since you don't have access to write there.
Instead of creating two layers of pointers, create a value of the type you want, and then pass the address (&) of that value; this will add the extra layer of pointer automatically.
// Create storage
var content: UnsafeMutablePointer<CChar>? // Could be NULL, so Optional
var length: Int32 = 0
var capacity: Int32 = 0
// Pass as references
do_something(&content, &length, &capacity)
// Copy the data
let data = Array(UnsafeRawBufferPointer(start: content, count: Int(length)))
content is still a pointer here because the thing being updated is a pointer. You're not providing storage for content, Rust is. But you do need to provide storage for the pointer (and that's what this does).
I can't compile your code because it's missing a lot (an MCVE would be much better here), so I can't test that this is doing exactly what you mean, but it should be close.
In your example, you're leaking the memory, but since your C# calls free_do_something_result (which I assume cleans it up), I assume you're actually doing the same in the Swift.
I'm trying to cast a 'filtered' array of a protocol type
I have a series of structs (Assessment, Level and Gate) that conform to several different Protocols - Stageable, Repeatable and Testable:
protocol Stageable
{
var index : Int { get }
var steps : [Step] { get }
}
protocol Testable
{
var threshold : Float { get }
}
protocol Repeatable
{
var sessions: Int { get }
}
struct Gate : Stageable, Testable, Repeatable
{
private(set) var index : Int
private(set) var steps : [Step]
private(set) var threshold : Float
private(set) var sessions : Int
}
struct Assessment : Stageable, Testable
{
private(set) var index : Int
private(set) var steps : [Step]
private(set) var threshold : Float
}
struct Level : Stageable, Repeatable
{
private(set) var index : Int
private(set) var steps : [Step]
private(set) var sessions : Int
}
Step is another struct. There are no classes being used.
These structs are populated just before being added to an array.
An array takes the form usually of [Assessment, Gate, Level, Level]. All the structs data is populated from an XML file.
In some instances I only want to review the 'Levels' in the array, so I do:
// stages = [Assessment, Gate, Level, Level, ...]
let levels = stages.filter{ $0 is Level }
If I query this, it looks fine e.g. levels.count is what I expect.
However, if I now want to cast the array to [Level] it crashes with the following error:
fatal error: can't unsafeBitCast between types of different sizes
Is this because I'm casting from a protocol to a struct type? I also feel like I've missed the key benefits of Protocols here and there must be a better way to do this.
Currently using Xcode 7 beta 5.
Casting arrays of structs is problematic because structs are value types. That means each element of an array of structs takes up the size of the struct in memory. This is different for arrays of standard objects because these are passed by reference. Each element in an array of objects is a reference (a pointer to a specific memory area).
To demonstrate this, consider the following
class ABC {
private var i = 0
private var j = 1
private var k = 2
}
print(sizeof(UIViewController))
print(sizeof(UIImage))
print(sizeof(NSObject))
print(sizeof(ABC))
Each of the print statements outputs 8 on my platform which is the size of a memory address (which is obviously different from the amount of memory occupied by instances of this class).
On the other hand, when I take the code from your question and do
print(sizeof(Stageable))
print(sizeof(Level))
I get 40 and 24 respectively which are the actual sizes of instances of these structs in memory. That means an array of type [Stageable] consists of chunks of 40 byte elements whereas an array of type [Level] consists of chunks of 24 byte elements. As a result you cannot cast between such array types because that would require the array's memory to be rewritten.
As an alternative, you can use the map method to force type conversion:
let levels = stages.filter({ $0 is Level }).map({ $0 as! Level })
The above can also be simplified by leveraging the flatMap method:
let levels = stages.flatMap({ $0 as? Level })
Well, when you execute this code:
let levels = stages.filter{ $0 is Level }
your levels type become [Stageable]. Now, to convert [Stageable] to [Level] you can use this code:
var l = levels.map{ $0 as! Level }
I am trying to write an abstract data type to represent sets of integer items
using linked lists but I am already stuck. I'm not sure if it is possible to refer to one struct declaration from another. Here is my attempt:
struct linkedListElement{
int data;
struct linkedListElement * next;
};
struct linkedListSet {
struct linkedListElement * firstElement;
struct linkedListElement * header;
struct linkedListElement * current;
struct linkedListElement * temp;
header = firstElement;
};
Is it possible to do it this way or is there an easier way?
It is possible for one struct definition to refer to another struct defintion – you do it correctly in your code:
struct linkedListSet {
struct linkedListElement * firstElement;
If you mean "set" as in "an unordered collection of items without duplicates", then the important logic will be in how you manipulate your underlying data structure to enforce those constraints. For example with your singly-linked list, you must iterate the entire list before adding an item to check for duplicates.
header = firstElement;
This line is not allowed in a struct definition.
None of the examples I have seen thus far appear to address the problem of marshaling a structure containing a union of structures that contain recursive references. I am attempting to write a marshaler for a structure which contains these and have so far failed.
For example:
typedef enum {
My_StructA = 0x7878,
My_StructB
} MyStructTag;
typedef struct _MyStruct MyStruct;
struct _MyStruct {
MyStructTag discriminator;
union {
struct {
int a;
int b;
} StructA;
struct {
int c;
MyStruct* d;
} StructB;
} MyUnion;
};
I attempted to define the structures as follows:
type MyStructTag =
| My_StructA = 0x7878
| My_StructB = 0x7879
[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructA =
val mutable a : int
val mutable b : int
[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructB =
val mutable c : int
val mutable d : MyStruct
[<Struct; StructLayout(LayoutKind.Explicit)>]
type MyStruct =
[<FieldOffset(0)>] val discriminator : MyStructTag
[<FieldOffset(4)>] val structA : StructA
[<FieldOffset(4)>] val structB : StructB
Note that the reason I bothered to define MyStruct explicitly is to allow myself to make use of Marshal.OffsetOf() and Marshal.SizeOf() when writing the custom marshaler for this structure. From what I have seen, writing a custom marshaler is the only way to handle unions. If I am wrong about that, references would be greatly appreciated!
The error I receive when writing the above code is:
error FS0039: The type 'MyStruct' is not defined
I assume this is because only discriminated union types can be defined recursively. However, I am not aware of any other way to represent these structures in F#.
Thank you in advance for your time.
You've got two problems. First of all, any mutually recursive types (whether discriminated unions, classes, or structs) need to be defined using
type A = ...
and B = ...
rather than
type A = ...
type B = ...
(and note that attributes can come before or after the word type, but only after the word and...). However, if you try this, you'll see that you just get a different error, because structs can't be directly recursive as fields of each other. If struct A had a field which was a struct B and struct B had a field which was a struct A (and either of them had any other fields), then the size would be infinite. Note that this is true of your C code as well - StructB contains a pointer to a MyStruct, not a MyStruct itself. In .NET, you can use an IntPtr for this - in F# you can use the nativeint alias or nativeptr<MyStruct>. Try this:
open System.Runtime.InteropServices
type MyStructTag =
| My_StructA = 0x7878
| My_StructB = 0x7879
[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructA =
val mutable a : int
val mutable b : int
[<Struct; StructLayout(LayoutKind.Sequential)>]
type StructB =
val mutable c : int
val mutable d : nativeptr<MyStruct>
and [<Struct; StructLayout(LayoutKind.Explicit)>]MyStruct =
[<FieldOffset(0)>] val discriminator : MyStructTag
[<FieldOffset(4)>] val structA : StructA
[<FieldOffset(4)>] val structB : StructB