CLI array initialization in value class - arrays

I know that value classes don't have an default constructor as the compiler initializes all elements in this class with zero. But arrays are in a value class are not initialized:
value class c_LocationVal
{
public:
double x, y, z;
c_LocationVal(double i_x, double i_y, double i_z) {x = i_x; y = i_y; z = i_z;}
};
typedef cli::array<c_LocationVal> arrloc;
value class c_Managed
{
public:
arrloc^ m_alocTest;
//c_Managed() { m_alocTest = gcnew arrloc(3); } --> not permitted
double funcManaged ()
{
return m_alocTest[0].x; --> error: Object reference not set to an instance of an object
}
};
I just could cheat and use:
c_Managed(int i) { m_alocTest = gcnew arrloc(3); }
but there must be another solution.
Can someone please tell me how to solve this?

The CLR only supports code inside of methods. Compilers emulate the behavior of a member initialization expression by creating a constructor, if necessary, and moving the code for the expression into the constructor.
Which explains why this isn't permitted, your expression requires a parameterless constructor and that's not legal for a value type.
Sure, your trick will work. But in general, you need to de-tune C++ assumptions a bit when you write C++/CLI code. There are no practical differences between a struct and a class in C++. But that's definitely not the case in managed code. Only ever use a value class for very simple types. Requiring initialization heavily tips the choice to a ref class. As does a value type having an array, you'd normally need a deep copy to make that work without accidents. Never fear the heap in C++/CLI, it is very fast.

A value class is always initialized with "null/0". So a managed reference in a value class will also always be initialized to "null". If you want to have a special initialization, then you only have the solution, you were pointing out: You need to create a special constructor which has some parameters to "initialize" the value class correctly.
The question is: Do you really need a value class which contains a managed reference??? Normally this should also be a ref class.
Also, what happens, if the value class is copied? What should happen with the reference? It will also directly copied! Is this intended? The goal of a value class is to provide a "real" copy! In your case it will not "fully copied"...
Pleas re-think if a value class is the best solution for your data storage...

Switch the public field to a property, and do lazy initialization when the property is retrieved.
value class c_Managed
{
private:
arrloc^ m_alocTest;
public:
arrloc^ AlocTest
{
arrloc^ get()
{
if(m_alocTest == nullptr)
{
msclr::lock(c_Managed::typeid)
if(m_alocTest == nullptr)
m_alocTest = gcnew arrloc(3);
}
return m_alocTest;
}
}
double funcManaged ()
{
return AlocTest[0].x;
}
};
The lock for the lazy initialization isn't ideal, but it's just about the only thing to lock on: this is a value type, so locking would box it and the lock would be on the box, not on the object itself. Since it's a value type, providing any reference type as a field to lock on would give a null reference, just like the array, so there's no help there. The only thing I can think to lock on is the type object itself for this type.

Related

Accessing a Struct as a Global Var in a .m file

I have a struct that contains pointers to values that must be used in several functions throughout my class. I typedef defined the type in the header,
typedef struct MyAUGraphPlayer {
AUGraph graph;
AudioUnit speechAU;
} MyAUGraphPlayer;
and declared it in the .m,
#implementation SpeechGraph {
MyAUGraphPlayer player;
}
However when trying to initialize it, I get the error `Unexpected expression' from this code (the error is on the line player = ...)
- (void)setup {
player = { 0 };
CreateMyAUGraph(&player);
}
The player variable is recognized as a MyAUGraph type but doing the conventional { 0 } assignment leads to a compile-time error.
I have built this Core-Audio code fine in a command line project but now I'm attempting to build a UI around it and apparently some of the mixing between the C core stuff and object oriented stuff is causing some confusion for me. I would greatly appreciate some help.
First: player is not a global variable. It is an instance variable (ivar) of SpeechGraph.
Second: In modern Objective-C, instance variables are initialized to 0 in newly alloced objects, by default. There is no need to set this value to 0 again. See Programming With Objective-C, "Working with Objects", "Objects Are Created Dynamically".
Third: If you really need to set the value, player = (MyAUGraphPlayer) { 0 }; should work. (This is an assignment, not an initialization. More about the difference.)
You can only initialise a variable when you first declare it. By the time your method gets called it’s already to late for initialisation.
What you are trying to do here is interpreted as an assignment by the compiler (only a = after the declaration is an initialisation!) – and the right hand value is a block here. This is what leads to a compiler error.
You’ll have to do it by hand (or not all).
I think you can only initialize a struct that way when declaring it.
MyAUGraphPlayer player = { 0 };
In your case you should use memset like this.
memset(&player,0,sizeof(MyAUGraphPlayer));

JNI -- C implementation with boolean values

This is a two part question. My first question relates to boolean values in the C portion of a JNI implementation. Since C doesn't have a boolean type, I am confused about how to do this. I have a Java object that looks like this:
public class JNIResult {
private boolean successful;
private String data;
public JNIResult(boolean successful, String data) {
this.successful = successful;
this.data = data;
}
}
On the C side, I want to create a new JNIResult object. I have gotten the constructor method ID, and now I am calling (*env)->NewObject(). Let's say, for instance, that I want to create this object:
JNIResult(true, null);
How would I do that in C? I know that it would be something like this:
jobject JNIResult = (*env)->NewObject(env, JNIResultClass, JNIResultConstructor, true, NULL);
but the boolean thing is confusing me.
Secondly, stemming from that question, when supplying parameters to a native Java method in C, whether it's a constructor or another method, what should the type be for those values? For instance, if I am calling a Java square root function that takes a double value as an argument, on the C side should I supply a jdouble or a double value to the function?
C normally uses the integer value 0 for "false" and 1 for "true". That way, the if statement will return the appropriate value.
This is explained in Using boolean values in C and the link is to the selected answer.
typedef enum { false, true } bool;
When I called a Java funtion from C, I had to create an intermediate JAVA function in order to make the appropriate changes and then use the intermediate Java function to call the java function.
Thus, instead of C calling JNIResult directly, hav it call an intermediate function in Java which will contain
boolean jbool;
typedef enum (myfalse, mytrue) mybool;
mybool cbool;
if (cbool == mytrue)
{
jbool = true;
}
else
{
jbool = false;
}
Now create your JNIResult object (in Java), make whatever changes need to be made before returning to C. You can use similar methods for any other situations when calling from one language to another.
#adelphus points out that JNI does the equivalent of what I show above within the JNI processing.
In JNI, Java boolean values are mapped to jboolean (which is an
unsigned char) - just inlclude jni.h and pass JNI_TRUE or JNI_FALSE. –
adelphus Jul 30 at 17:39

benifits/drawbacks of returning a const or final value/reference from any method

I am a novice programmer exploring the depths of C. Why does some inbuilt functions return a const value ? Can somebody explain the benefits or drawbacks of using const in method returns ?
Using final and const in returning values from functions and methods is to keep people from changing their values. For example, if i had (in c)
char* getChar()
{
return "string";
}
and I didn't want someone to use it like
char myChar = getChar()[0]++;
then i would have to return a const, to keep it from being changed.
For Java, it's very different. You don't return final values, you make methods final.
final is used with a Java method to mark that the method can't be overridden (for object scope) or hidden (for static). This allows the original developer to create functionality that he can be sure will not be changed by others, and that is all the guarantee it provides.
C's const and Java's final are very different, and especially in the case you're talking about.
In C (disclaimer: I haven't done C in a while so please let me know where I'm wrong) let's look at this example:
const int something() {
return 3;
}
The const is meaningless because it's not like you can do:
something() = 3;
For some more information on const return values in C, take a look at the following:
const makes no sense for return values...
Purpose of returning by const value (this is C++, but still useful).
In Java, I'm assuming you're talking about something like:
public final int something() {
...
}
Here final has nothing to do with the return value. final here means that if you extend the class that something() belongs to, you cannot override the implementation of something(). This is somewhat similar in spirit to final variables; these are variables whose values you cannot change once they are set.

Swift optional Array property is immutable?

I am constructing an array of booleans to store the state of the sections in a UICollectionView. It is a variable stored as a property of my UIViewController:
var _weekSelections : Array<Bool>!
Then, in a function called by loadView(), I construct the array and assign a value to the first index:
_weekSelections = Array<Bool>(count:_weekCount, repeatedValue:false)
_weekSelections[0] = true
The value at index 0 remains false! The array is constructed, and has multiple elements, but any assignment that I make to an index does not affect the value stored at that index, even if I check the value on the very next line of code. I know that Swift makes a copy of an array if I perform an action that may change its length, but I don't think this is a case where a copy would me made. The only way I can get any value to change is if I manually create a copy as follows:
var copy = _weekSelections
copy[0] = true
_weekSelections = copy
Am I missing something obvious or could this be a strange bug?
For the sake of having my code on SO rather than Pastebin, here's my observation. This looks like some kind of bug or unexpected behaviour when using an optional array in a Swift class derived from an Objective C class. If you use a plain Swift class, this works as expected:
class Foo {
var weekSelections: Array<Bool>!
func test() {
weekSelections = Array<Bool>(count: 10, repeatedValue: false)
weekSelections[0] = true;
println(weekSelections[0]) // Prints "true"
}
}
var foo = Foo()
foo.test()
However, if you derive Foo from NSObject:
import Foundation
class Foo : NSObject { // This derivation is the only difference from the code above
var weekSelections: Array<Bool>!
func test() {
weekSelections = Array<Bool>(count: 10, repeatedValue: false)
weekSelections[0] = true;
println(weekSelections[0]) // Prints "false"
}
}
var foo = Foo()
foo.test()
Even in this case, if you do your weekSelections initialisation in an initialiser, then it works:
class Foo : NSObject {
var weekSelections: Array<Bool>!
init() {
weekSelections = Array<Bool>(count: 10, repeatedValue: false)
weekSelections[0] = true;
println(weekSelections[0]) // Prints "true"
}
}
var foo = Foo()
Personally, I'd say that this is a bug. I can't see anything in any documentation that would explain the difference in behaviour when derived from NSObject.
I also can't see anything that says that optional array properties would be immutable. This would be especially strange when you consider that "immutable" arrays are actually mutable in Swift, i.e. this:
// Use "let" to declare an "immutable" array
let weekSelections = Array<Bool>(count: 10, repeatedValue: false)
weekSelections[0] = true;
println(weekSelections[0]); // Prints "true"; arrays are never really "immutable" in Swift
...works fine, and is currently documented as being valid, even if it seems a bit odd.
Personally, I'd use whatever workaround you can and raise a bug with Apple, to see what light they can shed.
Not an explanation, but a workaround. The issue isn't with the count:repeatedValue initializer, but rather with the array being assigned to an optional variable. From what I can tell optional arrays can only use accessor methods and not mutator methods--effectively they're immutable. Temporarily assigning _weekSelections to a non-optional variable before attempting to change its contents (and assigning back to _weekSelections when done) will work. Please note that this seems to create a new array (with the same elements) on assignments, so there may be memory issues to consider if the array is very big. Of course, simply using a non-optional variable in the first place will also work.
As for why optional arrays aren't mutable, that may be a bug or there may be some esoteric reason for it I'm not fathoming. Anyone else have a plausible-sounding theory?

How do I pass a class as an argument to a function in UnrealScript?

I want to do
result = TraceActors(class'QuadForcePawn', HitEnemy, hitLocation, HitNorm, weaponStart, m_oldWeaponStartLocation[iHand], vExtent);
but I want to substitute a variable for the class'QuadForcePawn' part. I haven't been able to figure out how to do this.
This is so I can have a function that calls TraceActors, and that function takes an argument telling it which kinds of Actors to look for.
Technically, TraceActors is actually an iterator function and is meant to be used with the foreach keyword, so you wouldn't actually assign the result to a variable.
To answer your question, what you want to use is a class reference variable. An example function might look like this (TraceActors actually requires many more parameters, but I've left them out for brevity.):
function TraceFor (class<Actor> traceClass)
{
local Actor A;
foreach TraceActors(traceClass, A)
{
// do work here
}
}
Class reference variables are declared with the class keyword, and optionally you can use the <> syntax to limit the classes which can be assigned to it. class<Actor> declares a class reference variable which can only have Actor or subclasses of Actor assigned to it. In the example function above, a call to TraceFor(class'Pawn') would work fine, but a call to TraceFor(class'Object') would fail to compile.
If you want to return the result of the TraceActors call, one way to do it might be to build an array of the results and return that:
// Returns an array of Actors of the passed in type.
function TraceFor (class<Actor> traceClass, out array<Actor> results)
{
local Actor A;
foreach TraceActors(traceClass, A)
{
results.AddItem(A);
}
}

Resources