I want to do this:
typedef struct
{
CGPoint vertices[];
NSUInteger vertexCount;
} Polygon;
But it says Field has incomplete type CGPoint [].
You need to do one of two things:
Declare the array to be a fixed size (probably not what you want)
Make it a pointer. But then you need to properly malloc and free the array as needed.
A better choice is to not use a struct and instead create a full class. Then you can add methods and properties as well as make memory management much easier. You are working in Objective-C. Take advantage of the Object Oriented aspects of the language. Add a method to calculate the circumference and area, etc. Put the logic where it belongs.
Set array size CGPoint vertices[count];
Don't you want a unique name for each element of your struct anyway? If you just want a bunch of CGPoint's in a numerical order, with the ability to count how many of them there are you'd be much better served by shoving them in an NSArray or NSMutableArray (stored as NSValue's of course)
The whole point of a struct would be to have easy access to the values by a descriptive name, ie:
typedef struct {
CGPoint helpfulAndDescriptiveNameOne;
CGPoint helpfulAndDescriptiveNameTwoWhichIsDifferentThanTheOtherName;
etc...
NSUInteger vertexCount;
}
For example, a CGRect is just a struct composed of four different CGFloats, each of which is descriptively and helpfully named:
typedef {
CGFloat x;
CGFloat y;
CGFloat width;
CGFloat height;
} CGRect;
Related
I am passing my metal kernel and shader functions a parameter structure. I can't find anywhere that specifies what Swift data types to use to match the data types in Metal.
I have done my best to guess what data types to use on the Swift side, but it seems to be very picky in what order I define the variables in my structs. Which leads me to believe that they are not aligned.
For instance, here are the data types I am using in Metal:
struct ComputeParameters {
bool yesNo;
int count;
float scale;
float2 point;
float4 color;
};
And here is my corresponding struct in Swift:
struct ComputeParameters {
var yesNo: Bool = false
var count: Int32 = 0
var scale: Float32 = 1.0
var point: float2 = float2(0.0, 0.0)
var color: float4 = float4(0.0, 0.0, 0.0, 1.0)
}
Here is a table of the datatypes I am using from above.
Metal _________ Swift
bool Bool
int Int32
float Float32
float2 float2
float4 float4
Are those correct? Is there somewhere the parameter datatypes are documented?
The size of the Int type in Swift depends on the target platform. It could be equal to Int32 or Int64, though these days it will almost always be Int64. So you should use the more explicit Int32 type to match Metal's 32-bit int type.
As of Swift 5, float2 and float4 are deprecated in favor of SIMD2<Float> and SIMD4<Float>, respectively. These correspond exactly with Metal's float2 and float4.
I believe the rest of your correspondences are correct.
However, it's probably not wise to define these structures in Swift in the first place. Swift gives you no guarantees regarding struct layout (padding, alignment, and member order). Therefore you could wind up with a layout mismatch between Swift and MSL (I haven't seen this happen, but the point is that it can).
The current guidance, I believe, is to define such structs in C/Objective-C instead and import them via a bridging header. That makes it more likely that memcpy-style copies of structs into Metal buffers will do the right thing. Always pay careful attention to size and alignment, especially since manual reordering of struct members can change the size and/or stride of the struct.
I want to find out if my CGMutablePathRef has more then 3 points! This checking will happen frequently so Im looking for an efficient solution.
This reason I need to do this is because in my project the user draws a shape. As the user drags his/her finger a CGPoint(current location of finger) is added to the path and a physical body is added when the touchEnded: is called.. now if the user just taps the screen the CGMutablePathRef only has one point in it(my reasoning in my head) and I get the following error when I use the my CGMutablePathRef for adding the physical body.
Assertion failed: (count >= 2), function CreateChain, file /SourceCache/PhysicsKit/PhysicsKit-6.5.4/PhysicsKit/Box2D/Collision/Shapes/b2ChainShape.cpp, line 45.
Im looking to make a function to call that takes a cgpathref as a parameter and counts the points until it reaches 3 (or the end if there isn't 3) and returns a bool
Thanks :)
If you want to enumerate the elements of a CGPath, you have to use CGPathApply, and there is no support for early termination. You must enumerate all of the elements.
Grab my Rob_forEachElementOfCGPath function from this answer, and use it like this:
int numberOfSegmentsInCGPath(CGPathRef path) {
__block int count = 0;
Rob_forEachElementOfCGPath(path, ^(const CGPathElement *element) {
if (element->type != kCGPathElementMoveToPoint) {
++count;
}
});
return count;
}
There's no particularly efficient way to do this, but you could keep track of the number of points as you add them.
#interface MyPath : NSObject
#property (assign) int pointCount;
#property (assign) CGPathRef path;
#end
If you wanted to make sure you had complete control over it (and didn't want to worry about someone else incrementing your count or changing your path without incrementing), you could make the properties readonly and have an 'add point' function on the object ... Not great, but it would be more efficient than ApplyPath.
I'm curious how I would use an if statement to see if a CGVector variable is nil, as objects are done like so:
if (!object){
//Do This
}
But with CGVector it's not an object (As I know of). How would I determine if my CGVector variable is nil?
As you know it is a struct not an object
struct CGVector {
CGFloat dx;
CGFloat dy;
};
typedef struct CGVector CGVector;
Edit:
There is no such thing to check if a struct is nil.
Even if you check with dx==0 and dy==0, this is not correct at all an {0,0} is still a valid vector point.
For similar approach/question : How do I check if a CGPoint has been initialised?
I have different size of pages. I want to use enum to select size of page. somethink like that
typedef NS_ENUM(CGSize, SizeType) {
MAXSIZE=CGSizeMake(640, 1196),
MIDIUMSIZE=CGSizeMake(320, 590),
MINSIZE=CGSizeMake(160, 280)
};
its possible? if not then whats the best way to do this i need this combine value in my whole application
An enum in C (and therefore in Objective-C) is a set of integer values, and that's why you cannot have CGSize values as members of it.
Instead, use constants. The best option is to look at what Apple does and mimic it.
If you take a look at CGGeometry.h you will find the definitions of various constants.
For instance, CGSizeZero is defined as
CG_EXTERN const CGSize CGSizeZero
CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
You can then do something similar by declaring a constant in your header
CG_EXTERN const CGSize kMaxSize;
and then defining it in the implementation
const CGSize kMaxSize = (CGSize){ 640, 1196 };
As a bonus you can also define a type synonym for CGSize, for instance:
typedef CGSize MySizeType;
and then use it for declaring both constants and variables, e.g.
CG_EXTERN const MySizeType kMaxSize;
...
#property (nonatomic) MySizeType aSize;
That does't change a bit from a technical point of view, but it's semantically nicer and it basically achieves the same purpose of a typedef enum (which is precisely providing a convenient synonym to int)
As per the other answers, enums are basically integers, not structs.
You can just #define the values in a constants file:
#define MAXSIZE CGSizeMake(640, 1196)
#define MIDIUMSIZE CGSizeMake(320, 590)
#define MINSIZE CGSizeMake(160, 280)
though you might want to rename them for easier mnemonics, readability and auto-completion purposes, like:
#define PURPOSE_SIZE_MAX ...
#define PURPOSE_SIZE_MED ...
...
You cannot.
The enum type is a C type and it must be integer types, each member must be the same type also.
You can use char, BOOL, int, uint, NSInteger and so on.
For constant floating point values, you will need to declare them one by one.
structs also need to be done one by one.
You can not use enum for this. In Objective C enum is inherited from C. So it is implicitly converted to int.
It seems I cannot make C++/CLI structures be aligned with less than 8 bytes. I have a struct of two Int32, allocate a million of them, and voilĂ : 16 MB memory according to ".NET Memory Profiler" (plus the list data). I set the compiler option to /Zp4 (also tried /Zp1), to Minimize Size (/O1) and Small Code (/Os), just to make sure, I additionally put a "#pragma pack(1)" into my code, to no avail. My struct is still taking up 16 Bytes. I changed it to class, still the same.
Why that?
How to change?
Ciao,
Eike
using namespace System;
#pragma pack(1)
ref struct myStruct
{
Int32 a;
Int32 b;
};
int main(array<System::String ^> ^args)
{
System::Collections::Generic::List<myStruct^> list;
for (int i = 0; i < 1000000; i++)
{
list.Add(gcnew myStruct());
}
// avoid optimization
Console::WriteLine(list[333333]->a);
return 0;
}
You need to use value types to be able to specify alignment. Beyond that I'm not sure this is the best way to measure this. Reference types also have some small built in overhead. Try value struct/value class instead.