How to store C Arrays as a Property or iVar?


Dave
 

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray = myArray;


Thanks a lot
All the Best
Dave


Alex Zavatone
 

You can save them as NSIntegers in an NSMutableArray.

The thing about NSDictionaries and NSArrays is that they need to contain NSObjects that are Cocoa Collections.


Someone please correct me if I’m tragically misguided.

But try that, Dave.

Cheers,
Alex Zavatone

On Aug 18, 2017, at 2:07 PM, Dave <dave@...> wrote:

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray =  myArray;


Thanks a lot
All the Best
Dave






Pascal Bourguignon
 


On 18 Aug 2017, at 21:07, Dave <dave@...> wrote:

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray =  myArray;


Yep.

Objective-C is C.

You have to know C to be able to program in Objective-C.

In C, arrays are not first class objects.  So you cannot use = to copy arrays (or to take a reference to an array, there’s no such notion in C).

The solution is to write a loop to copy the elements.

void copy_my_array(int src[10][10],int dst[10][10]){
    for(int i=0;i<10;++i){
        for(int j=0;j<10;++j){
            dst[i][j]=src[i][j];}}}

then use:

copy_my_array(myArray,_myArray);

-- 
__Pascal J. Bourguignon__




Jack Brindle
 

Can you publish the actual declarations for myArray and mArray? The ones you show aren’t quite legal and
will be rejected by C compilers.

There isn’t that much different from regular C. In your code, you are not creating a property, but rather an instance variable.
Thus it does not create anything named _mArray. If you created an @property var then the _mArray might work.
Struct assignment does work in Objective C. I don’t remember that arrays may be copied, though. Might that be a C++ extension?

- Jack

On Aug 18, 2017, at 12:07 PM, Dave <dave@looktowindward.com> wrote:

Hi All,

I’ve converted some C code into Objective-C and have some C Array structures like so:

int [10][10]) myArray;

That I want to store in a Property or iVar inside a Wrapper Class. How do I do this?

I’ve tried:


@interface WrapperClass : NSObect
{
int [10][10]) mArray;
}

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

or

_mArray = myArray;


Thanks a lot
All the Best
Dave




 


On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

You can't assign (or compare) arrays in C/C++. You have two options:

(a) Call memcpy:
memcpy(&myArray, &_mArray, sizeof(myArray));

(b) Wrap a struct around the array, since structs are copyable. Drawback is that you now have to refer to the array as a named field of the struct.
typedef struct {
int [10][10]  a;
} MyArrayType;
MyArrayType myArray;
_mArray = myArray;

(This is a pure C issue, so a book like K&R would be helpful.)

—Jens


Alex Zavatone
 


On Aug 18, 2017, at 3:04 PM, Jens Alfke <jens@...> wrote:


On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

You can't assign (or compare) arrays in C/C++. You have two options:

(a) Call memcpy:
memcpy(&myArray, &_mArray, sizeof(myArray));

(b) Wrap a struct around the array, since structs are copyable. Drawback is that you now have to refer to the array as a named field of the struct.
typedef struct {
int [10][10]  a;
} MyArrayType;
MyArrayType myArray;
_mArray = myArray;

(This is a pure C issue, so a book like K&R would be helpful.)

—Jens
_._,_._,_

In that light, is my suggestion useless overhead?



Dave
 

Hi Jens,

You solved two problem in one with your last post - thanks a lot!

I had some other information that was being passed back and forth and creating a structure allowed me to solve the Array copying problem and I could add the extra information fields to the struct!

Thanks again,
All the Best
Dave

On 18 Aug 2017, at 22:04, Jens Alfke <jens@...> wrote:


On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

You can't assign (or compare) arrays in C/C++. You have two options:

(a) Call memcpy:
memcpy(&myArray, &_mArray, sizeof(myArray));

(b) Wrap a struct around the array, since structs are copyable. Drawback is that you now have to refer to the array as a named field of the struct.
typedef struct {
int [10][10]  a;
} MyArrayType;
MyArrayType myArray;
_mArray = myArray;

(This is a pure C issue, so a book like K&R would be helpful.)

—Jens


 


On Aug 18, 2017, at 2:38 PM, Alex Zavatone <zav@...> wrote:

In that light, is my suggestion useless overhead?

(IIRC you suggested using an NSMutableArray of NSNumbers?) Honestly, it depends. It does have overhead, although not as much as it used to, since NSNumbers of reasonable-size integers don't allocate any memory (they're just tagged pointers.) On the plus side, you get array bounds checking, and it's easy to grow the array dynamically if you ever need to.

If you don't need high performance (e.g. you're not doing math-y stuff with these arrays) and you're not allocating millions of these, NSMutableArray is reasonable. Especially for those who aren't super comfortable with C.

—Jens


Dave
 

Hi,

It recurses through the cells in the Array and there could be around 7000 iterations, so I’d rather stick with normal integers.

One thing I was going to ask is that, the value range on each cell is 0 to 10, at the moment its using an “int” to hold this (which I assume is 32 bits), would there be a speed impact if I made it int16 or int8?

All the Best
Dave

On 
On 22 Aug 2017, at 17:47, Jens Alfke <jens@...> wrote:


On Aug 18, 2017, at 2:38 PM, Alex Zavatone <zav@...> wrote:

In that light, is my suggestion useless overhead?

(IIRC you suggested using an NSMutableArray of NSNumbers?) Honestly, it depends. It does have overhead, although not as much as it used to, since NSNumbers of reasonable-size integers don't allocate any memory (they're just tagged pointers.) On the plus side, you get array bounds checking, and it's easy to grow the array dynamically if you ever need to.

If you don't need high performance (e.g. you're not doing math-y stuff with these arrays) and you're not allocating millions of these, NSMutableArray is reasonable. Especially for those who aren't super comfortable with C.

—Jens


Dave
 

Hi,

It recurses through the cells in the Array and there could be around 7000 iterations, so I’d rather stick with normal integers.

One thing I was going to ask is that, the value range on each cell is 0 to 10, at the moment its using an “int” to hold this (which I assume is 32 bits), would there be a speed impact if I made it int16 or int8?

All the Best
Dave

On 22 Aug 2017, at 12:01, Dave <dave@...> wrote:

Hi Jens,

You solved two problem in one with your last post - thanks a lot!

I had some other information that was being passed back and forth and creating a structure allowed me to solve the Array copying problem and I could add the extra information fields to the struct!

Thanks again,
All the Best
Dave

On 18 Aug 2017, at 22:04, Jens Alfke <jens@...> wrote:


On Aug 18, 2017, at 12:07 PM, Dave <dave@...> wrote:

But I get an error if I try to assign or read it, as in:

myArray = _mArray;

You can't assign (or compare) arrays in C/C++. You have two options:

(a) Call memcpy:
memcpy(&myArray, &_mArray, sizeof(myArray));

(b) Wrap a struct around the array, since structs are copyable. Drawback is that you now have to refer to the array as a named field of the struct.
typedef struct {
int [10][10]  a;
} MyArrayType;
MyArrayType myArray;
_mArray = myArray;

(This is a pure C issue, so a book like K&R would be helpful.)

—Jens



 



On Aug 23, 2017, at 3:28 AM, Dave <dave@...> wrote:

It recurses through the cells in the Array and there could be around 7000 iterations, so I’d rather stick with normal integers.

The time to read and unwrap an integer from an NSArray is probably under a microsecond, so it's unlikely to be a performance problem.

But there's nothing wrong with using a C array. It's what I'd do, personally.

One thing I was going to ask is that, the value range on each cell is 0 to 10, at the moment its using an “int” to hold this (which I assume is 32 bits), would there be a speed impact if I made it int16 or int8?

Yes, because the array will be smaller so it will take up less space in the CPU cache, causing fewer cache misses. But here the difference will be a few nanoseconds.

—Jens


Jeff Laing
 

Can I ask if this discussion is academic or you have already tried?

The reason I ask is that property values tend to need to support the NSObject protocol (ie, do the retain/release thing, whether manually or ARC) and I've always been given compilation failures whenever I try to start involving raw C memory management in that space.


 



On Aug 24, 2017, at 4:16 PM, Jeff Laing <jefflaing@...> wrote:

The reason I ask is that property values tend to need to support the NSObject protocol (ie, do the retain/release thing, whether manually or ARC) and I've always been given compilation failures whenever I try to start involving raw C memory management in that space.

No one said this was a property. It's just an instance variable.

Also, it's fine for properties to be C types — after all, there are plenty of integer or boolean properties, and UIKit and AppKit have properties whose types are structs like NSPoint and CGRect. I don't think a raw C array will work, since as mentioned before arrays aren't assignable in C, but a struct wrapping an array works fine.

—Jens


Jeff Laing
 

No one said this was a property. It's just an instance variable.

Um, the headline says "How to store C Arrays as a Property ..." so at least one person (the original poster) has said this is about properties.

My experience was that properties that are non-pointers work just fine, hence ints, reals, etc. but as soon as you start using pointers, the compiler starts squarking about ARC not liking those things.

I can see you are advocating a struct containing a fixed-size array and that may well work for the original poster - but if the array had been dynamically allocated, then I think it would have failed, the difference being that the compiler can believe it knows how to clone a fixed-size array (memcpy) whereas it can't be confident about indirect memory.


Alex Zavatone
 

Is there a reason why he shouldn’t represent the values as NIntegers like I suggested before?  I didn’t see a response to my suggestion explaining why it’s not a good idea.

[myArray addObject:[NSNumber numberWithInt:myValue]];
[myArray addObject:@myValue];
[myArray addObject:@(myValue)];









On Aug 25, 2017, at 12:37 AM, Jeff Laing <jefflaing@...> wrote:

No one said this was a property. It's just an instance variable.

Um, the headline says "How to store C Arrays as a Property ..." so at least one person (the original poster) has said this is about properties.

My experience was that properties that are non-pointers work just fine, hence ints, reals, etc. but as soon as you start using pointers, the compiler starts squarking about ARC not liking those things.

I can see you are advocating a struct containing a fixed-size array and that may well work for the original poster - but if the array had been dynamically allocated, then I think it would have failed, the difference being that the compiler can believe it knows how to clone a fixed-size array (memcpy) whereas it can't be confident about indirect memory.



Dave
 

Well, you can’t use them as a property anyway, C Arrays *have* to be iVar’s, but I wrap a “Property Wrapper” around the iVars!

On 25 Aug 2017, at 07:37, Jeff Laing <jefflaing@...> wrote:

No one said this was a property. It's just an instance variable.

Um, the headline says "How to store C Arrays as a Property ..." so at least one person (the original poster) has said this is about properties.

My experience was that properties that are non-pointers work just fine, hence ints, reals, etc. but as soon as you start using pointers, the compiler starts squarking about ARC not liking those things.

I can see you are advocating a struct containing a fixed-size array and that may well work for the original poster - but if the array had been dynamically allocated, then I think it would have failed, the difference being that the compiler can believe it knows how to clone a fixed-size array (memcpy) whereas it can't be confident about indirect memory.



Dave
 

You could do that, but I’m doing millions of calculations on the elements of the Array, so it would be a lot slower and much more complex than needed……

On 25 Aug 2017, at 15:35, Alex Zavatone <zav@...> wrote:

Is there a reason why he shouldn’t represent the values as NIntegers like I suggested before?  I didn’t see a response to my suggestion explaining why it’s not a good idea.

[myArray addObject:[NSNumber numberWithInt:myValue]];
[myArray addObject:@myValue];
[myArray addObject:@(myValue)];









On Aug 25, 2017, at 12:37 AM, Jeff Laing <jefflaing@...> wrote:

No one said this was a property. It's just an instance variable.

Um, the headline says "How to store C Arrays as a Property ..." so at least one person (the original poster) has said this is about properties.

My experience was that properties that are non-pointers work just fine, hence ints, reals, etc. but as soon as you start using pointers, the compiler starts squarking about ARC not liking those things.

I can see you are advocating a struct containing a fixed-size array and that may well work for the original poster - but if the array had been dynamically allocated, then I think it would have failed, the difference being that the compiler can believe it knows how to clone a fixed-size array (memcpy) whereas it can't be confident about indirect memory.




Gary L. Wade
 

If you want an actual property encapsulating your C-based array, you could keep it within an NSMutableData object since it’s just bytes.  I’m not sure if an NSData object would keep the actual data read-only (it’s certainly not growable), but it’s a VM-based optimization I’d expect to be a possible reason for not using NSData.

On Aug 25, 2017, at 6:54 AM, Dave <dave@...> wrote:

You could do that, but I’m doing millions of calculations on the elements of the Array, so it would be a lot slower and much more complex than needed……

On 25 Aug 2017, at 15:35, Alex Zavatone <zav@...> wrote:

Is there a reason why he shouldn’t represent the values as NIntegers like I suggested before?  I didn’t see a response to my suggestion explaining why it’s not a good idea.

[myArray addObject:[NSNumber numberWithInt:myValue]];
[myArray addObject:@myValue];
[myArray addObject:@(myValue)];









On Aug 25, 2017, at 12:37 AM, Jeff Laing <jefflaing@...> wrote:

No one said this was a property. It's just an instance variable.

Um, the headline says "How to store C Arrays as a Property ..." so at least one person (the original poster) has said this is about properties.

My experience was that properties that are non-pointers work just fine, hence ints, reals, etc. but as soon as you start using pointers, the compiler starts squarking about ARC not liking those things.

I can see you are advocating a struct containing a fixed-size array and that may well work for the original poster - but if the array had been dynamically allocated, then I think it would have failed, the difference being that the compiler can believe it knows how to clone a fixed-size array (memcpy) whereas it can't be confident about indirect memory.




 



On Aug 24, 2017, at 10:37 PM, Jeff Laing <jefflaing@...> wrote:

My experience was that properties that are non-pointers work just fine, hence ints, reals, etc. but as soon as you start using pointers, the compiler starts squarking about ARC not liking those things.

NSData.bytes is a property of type "void*". And NSPointerFunctions even has a property whose type is a C function pointer:

@property (nullable) BOOL (*isEqualFunction)(const void *item1, const void*item2, NSUInteger (* _Nullable size)(const void *item));

ARC doesn't give a damn about C types, generally; it only pays attention to Obj-C references. The one C thing ARC will complain about is if you put an Obj-C reference type in a C struct, because there's no way to update the object's ref-count during the lifetime of the struct. (And that restriction goes away in C++ because ARC can add code to the constructor/destructor.)

I can see you are advocating a struct containing a fixed-size array and that may well work for the original poster - but if the array had been dynamically allocated, then I think it would have failed, the difference being that the compiler can believe it knows how to clone a fixed-size array (memcpy) whereas it can't be confident about indirect memory.

I've already pointed that out at least twice in this thread. That's just basic C; you can't write a plain C function that returns an array, for example.

—Jens


 



On Aug 25, 2017, at 6:35 AM, Alex Zavatone <zav@...> wrote:

Is there a reason why he shouldn’t represent the values as NIntegers like I suggested before?  I didn’t see a response to my suggestion explaining why it’s not a good idea.


—Jens