What is the C++ CLI equivalent of managed c++'s __typeof and __gc? - c++-cli

I'm trying to convert an old c++ project from VS2003 to VS2019. Part of this, I'm learning, is going from managed C++ to C++ CLI as managed c++ was dropped pretty quickly.
I'm managing for the most part, but I can't seem to figure out what replaces the __typeof keyword. Is there a drop in for this? See below code snippet for context in how it was it's used.
private: System::ComponentModel::IContainer ^ components;
private:
void InitializeComponent(void)
{
this->components = gcnew System::ComponentModel::Container();
System::Resources::ResourceManager ^ resources = gcnew System::Resources::ResourceManager(__typeof(USB::Form1));
.
.
.
}
Additionally, there's another reoccurring identifier, __gc , that I have found some more info on, but am not sure I understand what to replace it with.
Char chars __gc[] = gcnew Char __gc[bytes->Length * 2];
Char hexDigits __gc[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
bool ImageNumberUsed __gc[];
Does anyone have a good grasp on this and know what the proper conversions are given above contexts?

I can't say that I've used much Managed C++, but I can say what the C++/CLI equivalents are.
__typeof(type) --> type::typeid
Access typeid as if it were a static field or property of the given type.
Returns an object of type System::Type^.
Example: gcnew System::Resources::ResourceManager(USB::Form1::typeid);
__gc[] --> class cli::array
cli::array is a full-fledged managed type. You create it with gcnew, variables are declared with the hat ^, etc.
cli::array is generic on the type of object stored in the array, and on the number of dimensions in the array (which defaults to 1). The size of the array is specified via a constructor parameter (using parentheses, not square brackets).
Variables are declared with the name of the type, cli::array. Square brackets are used for reading & writing values, not for declaring the type, nor for creating the array.
If the type inside the array is a managed reference type, you'll need to include the hat ^ inside the generic type. Example: cli::array<String^>^ foo = ...
Examples:
cli::array<System::Char>^ chars = gcnew cli::array<System::Char>(bytes->Length * 2);
cli::array<System::Char>^ hexDigits = { '0', '1', .... };
(I like to say System.Char, as an extra reminder that it's not the same thing as lower-case char.)
cli::array<bool>^ ImageNumberUsed; (Uninitialized or null until assigned)
Two-dimensional: cli::Array<String^, 2>^ stringGrid = gcnew cli::Array<String^, 2>(10, 10);

Related

How to represent ObjC enum AVAudioSessionPortOverride which has declaration of int and string using Dart ffi?

I'm working on a cross platform sound API for Flutter.
We're trying to stop using Objective C/Swift for the iOS portion of the API and we're using Dart ffi as a replacement.
ffi(foreign function interface) allows dart to call into an Obj C API.
This means we need to create a dart library which wraps the Obj C audio library.
Whilst doing this we encountered the AVAudioSessionPortOverride enum which has two declarations; AVAudioSessionPortOverrideSpeaker = 'spkr' and AVAudioSessionPortOverrideNone = 0.
I'm confused as to what's going on here as one of these declarations is an int whilst the other is a string.
I note that AVAudioSessionPortOverride extends an NSUInteger so how is the string being handled. Is it somehow being converted to an int? if so any ideas on how I would do this in dart?
Here's what we have so far:
class AVAudioSessionPortOverride extends NSUInteger {
const AVAudioSessionPortOverride(int value) : super(value);
static AVAudioSessionPortOverride None = AVAudioSessionPortOverride(0);
static const AVAudioSessionPortOverride Speaker =
AVAudioSessionPortOverride('spkr');
}
'spkr' is in fact an int. See e.g. How to convert multi-character constant to integer in C? for an explanation of how this obscure feature in C works.
That said, if you look at the Swift representation of the PortOverride enum, you'll see this:
/// For use with overrideOutputAudioPort:error:
public enum PortOverride : UInt {
/// No override. Return audio routing to the default state for the current audio category.
case none = 0
/// Route audio output to speaker. Use this override with AVAudioSessionCategoryPlayAndRecord,
/// which by default routes the output to the receiver.
case speaker = 1936747378
}
Also, see https://developer.apple.com/documentation/avfoundation/avaudiosession/portoverride/speaker
Accordingly, 0 and 1936747378 are the values you should use.
Look at this
NSLog(#"spkr = %x s = %x p = %x k = %x r = %x", 'spkr', 's', 'p', 'k', 'r' );
Apple is doing everything your lecturer warned you against. You can get away with this since the string is 4 chars (bytes) long. If you make it longer you'll get a warning. The string gets converted to an int as illustrated in the code snippet above. You could reverse it by accessing the four bytes one by one and printing them as a character.
Spoiler - it will print
spkr = 73706b72 s = 73 p = 70 k = 6b r = 72

Different Objective-C enums with the same literals

I wish to have two different enums, but they might have the same literal; for example:
typedef enum {ONE,TWO,THREE,FOUR,FIVE,SIX} NumbersEnum;
typedef enum {ONE,TWO,THREE,FIVE,EIGHT} FibonacciEnum;
This will raise a compile error because ONE, TWO, THREE, FIVE are repeated in both enums.
Is there a way to make this work as-is (not changing the literals' names or adding a prefix or suffix)?
Is there any way my code using the literals can look like this: int num = NumbersEnum.SIX; and not like this int num = SIX;?
No. That's part of the C and Objective-C language from the beginning of time. You're not going to change it, and nobody is going to change it for you.
You cannot do this with enums; their members are global and the names must be unique. There is, however, a neat technique you can use to make pseudo-namespaces for constants with structs.
Declare your "namespace" in the appropriate header:
extern const struct _FibonacciNumbers
{
int one;
int two;
int three;
int five;
} FibonacciNumbers;
Then initialize the values in an implementation file:
const struct _FibonacciNumbers FibonacciNumbers = {
.one = 1,
.two = 2,
.three = 3,
.five = 5
};
You now access a constant as, e.g., FibonacciNumbers.one, and other struct types can use the same names since the names are private to each of them.
So that's "No" for your first option, but "Yes" to the second.

Using C style unsigned char array and bitwise operators in Swift

I'm working on changing some Objective-C Code over to Swift, and I cannot figure out for the life of me how to take care of unsigned char arrays and bitwise operations in this specific instance of code.
Specifically, I'm working on converting the following Objective-C code (which deals with CoreBluetooth) to Swift:
unsigned char advertisementBytes[21] = {0};
[self.proximityUUID getUUIDBytes:(unsigned char *)&advertisementBytes];
advertisementBytes[16] = (unsigned char)(self.major >> 8);
advertisementBytes[17] = (unsigned char)(self.major & 255);
I've tried the following in Swift:
var advertisementBytes: CMutablePointer<CUnsignedChar>
self.proximityUUID.getUUIDBytes(advertisementBytes)
advertisementBytes[16] = (CUnsignedChar)(self.major >> 8)
The problems I'm running into are that getUUIDBytes in Swift seems to only take a CMutablePointer<CUnsignedChar> object as an argument, rather than an array of CUnsignedChars, so I have no idea how to do the later bitwise operations on advertisementBytes, as it seems it would need to be an unsignedChar array to do so.
Additionally, CMutablePointer<CUnsignedChar[21]> throws an error saying that fixed length arrays are not supported in CMutablePointers in Swift.
Could anyone please advise on potential work-arounds or solutions? Many thanks.
Have a look at Interacting with C APIs
Mostly this
C Mutable Pointers
When a function is declared as taking a CMutablePointer
argument, it can accept any of the following:
nil, which is passed as a null pointer
A CMutablePointer value
An in-out expression whose operand is a stored lvalue of type Type,
which is passed as the address of the lvalue
An in-out Type[] value,
which is passed as a pointer to the start of the array, and
lifetime-extended for the duration of the call
If you have declared a
function like this one:
SWIFT
func takesAMutablePointer(x: CMutablePointer<Float>) { /*...*/ } You
can call it in any of the following ways:
SWIFT
var x: Float = 0.0
var p: CMutablePointer<Float> = nil
var a: Float[] = [1.0, 2.0, 3.0]
takesAMutablePointer(nil)
takesAMutablePointer(p)
takesAMutablePointer(&x)
takesAMutablePointer(&a)
So you code becomes
var advertisementBytes = CUnsignedChar[]()
self.proximityUUID.getUUIDBytes(&advertisementBytes)
advertisementBytes[16] = CUnsignedChar(self.major >> 8)

c, obj c enum without tag or identifier

im learning cocos2d [open gl wrapper for objective C on iPhone], and now playing with sprites have found this in a example,
enum {
easySprite = 0x0000000a,
mediumSprite = 0x0000000b,
hardSprite = 0x0000000c,
backButton = 0x0000000d,
magneticSprite = 0x0000000e,
magneticSprite2 = 0x0000000f
};
...
-(id) init
{...
/second sprite
TSprite *med = [TSprite spriteWithFile:#"butonB.png"]; //blue
[med SetCanTrack:YES];
[self addChild: med z:1 tag:mediumSprite];
med.position=ccp(299,230);
[TSprite track:med];
so the variable defined in the enum is used in the tag name of the created sprite object,
but i don understand
why give values in hexa to the tags to use
the enum with out tags
as I knew this enum in obj C and C
typedef enum {
JPG,
PNG,
GIF,
PVR
} kImageType;
thanks!
Usually, when you are creating an enum, you want to use it as a type (variable, method parameters etc.).
In this case, it's just a way how to declare integer constants. Since thay don't want to use the enum as type, the name is not necessary.
Edit:
Hexadecimal numbers are commonly used when the integer is a binary mask. You won't see any operators like +,-,*,/ used with such a number, you'll see bitwise operators (!, &, |, ^).
Every digit in a hexadecimal number represents 4 bits. The whole number is a 32-bit integer and by writing it in hexadecimal in this case, you are saying that you are using only the last four bits and the other bits can be used for something else. This wouldn't be obvious from a decimal number.
Enums are automatically assigned values, incremented from 0 but you can assign your own values.
If you don't specify any values they will be starting from 0 as in:
typedef enum {
JPG,
PNG,
GIF,
PVR
} kImageType;
But you could assign them values:
typedef enum {
JPG = 0,
PNG = 1,
GIF = 2,
PVR = 3
} kImageType;
or even
typedef enum {
JPG = 100,
PNG = 0x01,
GIF = 100,
PVR = 0xff
} kImageType;
anything you want, repeating values are ok as well.
I'm not sure why they are given those specific values but they might have some meaning related to use.
Well, you seem to be working off a terrible example. :)
At least as far as enums are concerned. It's up to anyone to define the actual value of an enum entry, but there's no gain to use hex numbers and in particular there's no point in starting the hex numbers with a through f (10 to 15). The example will also work with this enum:
enum {
easySprite = 10,
mediumSprite,
hardSprite,
backButton,
magneticSprite,
magneticSprite2
};
And unless there's some point in having the enumeration start with value 10, it will probably work without specifying any concrete values.

Why argv[] is declared as const?

In Objective-C, why argv[] is declared as const:
int main(int argc, const char *argv[]) { }
Because const denotes that the value (char *) is immutable, which arguments are.
Once program arguments are handed off to a program, their values should not be modifiable.
Think of this array as an array of const char *'s, which in turn, is an array of chars.
So, say you passed the string "hello world" to your program as arguments, argv would look like this:
{{'h', 'e', 'l', 'l', 'o', '\0'}, {'w', 'o', 'r', 'l', 'd', '\0'}}
Because it makes writing the shell/program launcher/etc simpler while not making most programs much more complicated.
And the creators of 'C' were thinking ahead to make OS writers jobs easier - especially their own!