How to cast String to TValue? - c++builder

This code throws Invalid typecast at the last line prop->SetValue(control, value).
I assume I am casting "MyString" incorrectly. What's the right way to it?
for (int i = 0; i < MyForm->ControlCount; i++) {
TControl *control = MyForm->Controls[i];
if (control->Name == "MyTEdit") {
TRttiContext ctx;
TRttiType *type = ctx.GetType(control->ClassInfo());
TRttiProperty *prop = type->GetProperty(L"Text");
TValue value = TValue::From("MyString");
prop->SetValue(control, value);
}
}
It's supposed to loop through all the controls in MyForm until it finds the TEdit with the Name of MyTEdit, and change the text in the box to MyString.
My code is based on this answer. Unfortunately it did not provide an example of casting a String literal so a TValue so I am at a loss.
Update
After reading the answer to this question, I changed TValue value = TValue::From("MyString"); to this:
String myString = "MyString";
TValue value = TValue::From<UnicodeString>(myString);
Now I get the following error:
[ilink32 Error] Error: Unresolved external 'System::Rtti::TValue __fastcall System::Rtti::TValue::From<System::UnicodeString>(System::UnicodeString)' referenced from UNIT1.OBJ
I have included this at the top of Unit1.cpp:
#pragma explicit_rtti
#include <System.Rtti.hpp>
So I don't understand why it would say that.
Update 2
The problem disappeared when I switched to 64 bit from 32 bit.

TValue::From<T>() is a Delphi Generic method, and there are documented linker issues using Generics in C++:
How to Handle Delphi Generics in C++.
Try using the assignment operator= instead, as TValue has an assignment operator for UnicodeString:
String myString = "MyString";
TValue value;
value = myString;
TValue value;
value = String("MyString");

Related

ExpandEnvironmentStringsA() String Subscript out of range

I have a Function which checks to see if IIS is installed and gets the installation path.
int IsIISInstalled(string &pathname)
{
DWORD returnvalue;
long keyres = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\InetStp\\", 0, KEY_READ, &miva);
if (keyres == ERROR_SUCCESS)
{
char szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError;
nError = RegQueryValueExA(miva, "InstallPath", NULL, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (nError == ERROR_SUCCESS)
{
char retBuffer[512];
DWORD nsize = sizeof(retBuffer);
returnvalue = ExpandEnvironmentStringsA(szBuffer, retBuffer, nsize);
pathname = retBuffer;
}
}
if (!pathname.empty())
return 1;
else
return 0;
}
When i attach to my executable and debug this there is a return value from ExpandEnvironmentStringsA
in retBuffer showing the installation path. returnvalue shows 28 as is the TCHARS that was put in the buffer. Once i step into the next line setting the string pathname to the retBuffer it fails giving me a string subscript out of range. I understand what that error means, i have done it plenty of times. What is odd to me is if i specify a new string var in the function:
string fakeresult;
and set fakeresult to retBuffer:
fakeresult = retBuffer;
just as i am in the code above it passes through just fine with no errors. I am calling the function with this code.
string iis_path, miva_path;
int disable;
char *full_path;
//getMivaLocation(miva_path);
bool good2go;
int iisinstalled, empressaReturn, miaReturn;
iisinstalled = IsIISInstalled(iis_path);
Does this have to do with the fact i am passing pathname by reference to the function?
If that is the case why?
How could i fix this to be able to return my data?
I am not a well educated c++ coder i am learning a lot of this as i go and have learned much from you guys. Hoping someone has an idea on this as i do not wish to spend much more time researching to no avail. Thanks.
After stepping into further i found that the pathname is being set as it should. It is immediately crashing on the next call to another functions so my debugging was incorrect. Now i have scoped further hopefully i can fix this. Also for my own note, the reason why it would not crash when i set fakestring instead of pathname was due to the fact i was passing pathname in the function call that is crashing. With no value it is not setting something out of its scope.

Passing an object that undergoes default argument promotion to 'va_start'

This is my first Xcode app and objective-c so give me some slack :)
I tried googling on the issue but I cannot see any help regarding Xcode and app development. I added the error masseages after //
- (id)initWithBytes:(int8_t)byte1, ... { //Error: 1. Parameter of type 'int8_t' (aka 'signed char') is declared here
va_list args;
va_start(args, byte1); //Error: Passing an object that undergoes default argument promotion to 'va_start' has undefined behavior
unsigned int length = 0;
for (int8_t byte = byte1; byte != -1; byte = va_arg(args, int)) {
length++;
}
va_end(args);
if ((self = [self initWithLength:length]) && (length > 0)) {
va_list args;
va_start(args, byte1); // Error: Passing an object that undergoes default argument promotion to 'va_start' has undefined behavior
int i = 0;
for (int8_t byte = byte1; byte != -1; byte = va_arg(args, int)) {
_array[i++] = byte;
}
va_end(args);
}
return self;
}
Thank you in advance!!
va_start() saves the pointer to the first argument passed to the function into a va_list.
The arguments themselves are passed via a hardware stack.
The issue with int8_t comes from the way the hardware stack is implemented. (in x86 at least)
Just like the SSE and MMX does, the stack requires elements stored on it to have an alignment equal to a multiple of 16bits, so everything passed to the function WILL have at least 16 bits of size, regardless of its type.
But the problem is va_arg() doesn't know about all that. Historically, it was a macro, and all it does is returning a pointer stored in va_list, and incrementing va_list by sizeof(type).
So, when you retrieve the next argument, the pointer returned does not point to the next argument but one byte before it, or not - depending on whether the va_arg is a macro or a compiler built-in function.
And this is what a warning is about.
IMO at least. Pardon my English, It's my 2nd language.

What clang function(s) can I use to find such declarations that has '&',such as 'int *m = &b'?

I want to find declarations that has '&'; such as int *m = &b, then do something translations on such declarations.
Now, I use ASTMatcher varDecl() to find all VarDecl, and use declVar->getType().getTypePtr().getAs<clang::PointerType>() to get the pointer declartions.
What functions can I use to find such 'm = &b' declarations next?
Matcher.addMatcher(varDecl(unless(parmVarDecl())).bind("varDecl"), &VarD);
virtual void run(const MatchFinder::MatchResult &Result) {
ASTContext *Context = Result.Context;
SourceManager &sourceManager_ = Context->getSourceManager();
const VarDecl *declVar = Result.Nodes.getNodeAs<VarDecl>("varDecl");
const clang::Type *type = declVar -> getType().getTypePtr();
const clang::PointerType *pointer_type = type -> getAs
<clang::PointerType>();
if(pointer_type != NULL){
// what functions can I use to find m=&b
}
}
& is the unary operator inside of the variable declaration initialization. This makes the following matcher:
varDecl(unless(parmVarDecl()), hasInitializer(unaryOperator(hasOperatorName("&"))))
NOTE: you can utilize a useful little tool by clang team: clang-query. It helps you to check your matchers interactively.
Have a happy hacking with clang!

Objective-C passing object to function is always by reference or or by value?

In objective-c I am passing NSMutableDictionary to function and modifying it inside function it returns modified mutable dictionary :
NSMutableDictionary *obj2 = [[NSMutableDictionary alloc]initWithObjectsAndKeys:#"hello",#"fname",nil];
[self callerDictionary:obj2];
NSLog(#"%#",obj2[#"fname"]);//printing "Hi"
-(void)callerDictionary:(NSMutableDictionary*)obj
{
obj[#"fname"] = #"Hi";
}
Technically, Objective C always passes parameter by value, as does C, but practically when you pass an object you need to pass a pointer. While this pointer is passed by value, the semantics of Objective-C give the same effect as if you had passed an object reference; if you modify the objected that is pointed to by the pointer then you are modifying the same object instance that is pointed to in the calling context. The common terminology used in Objective C programming is "object reference" even though it is really a pointer value.
You can see from the * in the method signature that it is a pointer (or object reference in the common usage). If you are passing an intrinsic type, such as an int then it is passed by value unless you explicitly declare the method as requiring a reference:
For example:
-(void) someFunction:(int *)intPointer {
*intPointer = 5;
}
would be called as
int someInteger = 0;
[self someFunction: &someInteger];
// someInteger is now 5
The distinction between a pointer value and a true object reference can be seen in comparison to Swift which uses true references;
If I have
-(void)someFunction:(NSString *)someString {
int length = [someString length];
}
and then do
NSMutableArray *array = [NSMutableArray new];
[someFunction: (NSString *)array];
I will get a runtime exception since array doesn't have a length method, but the compiler can't confirm the type I am passing since it is a pointer.
If I attempted the equivalent in Swift then I will get a compile time error since it knows that the type coercion will always fail
All objects in Objective C passed by reference.
All C types such as NSUInteger, double etc. passed by value
C and Objective-C always pass parameters by value. Objective-C objects are always accessed through a reference (i.e. a pointer). There is a difference between a variable type (int, pointer, etc.) and the way variables are passed as function parameters. The use of the term reference in both scenarios can cause confusion.
by-value:
void f(int a) {
a = 14;
}
int a = 5;
NSLog(#"%d", a); // prints: 5
f(a);
NSLog(#"%d", a); // prints: 5
The value 5 is printed both times because the function f() is given a copy of the value of a, which is 5. The variable referenced within the function is not the same variable that was passed in; it is a copy.
In C++, you can have functions that take parameters by reference.
by-reference:
void f(int &a) {
a = 14;
}
int a = 5;
NSLog(#"%d", a); // prints: 5
f(a);
NSLog(#"%d", a); // prints: 14
Note the & in the function signature. In C++ (but not C, nor Objective-C), this means that the parameter is passed by reference. What this means is that a reference (pointer) to a is passed to the function. Within the function, the a variable is implicitly dereferenced (remember, it's really a pointer, but you don't treat it as one), and the original a variable declared outside the function is changed.
In C and Objective-C, passing a pointer to a function is functionally equivalent to using a reference parameter in C++. This is because a copy of the address is given to the function (remember, the parameter is still passed by value), and that address points to the same object instance that the original pointer does. The reason you don't see any explicit pointer dereferencing within the function (similar to the C++ reference) is because Objective-C syntax for object access always implicitly dereferences -- being within a function doesn't change this behavior.

Save int variable to Parse Object

I have a variable int and i want to save this to a PFObject. Whenever I try I get the error:
incompatible integer to point value from int to id.
I can add a normal int which is not in a variable by doing.
PFObject* object = [PFObject objectwithclassname:#"test"];
object[#"score"] = #30;
This works fine, and also I can add a string and it will work. It is when I try this that it does not work.
int test = 10;
object[#"score"] = test;
Anyone know?
The syntax is:
object[#"score"] = #(test);
Variables of type int are no (Objective-C) objects. You use the keyed subscription protocol for assignment. It only takes objects. Basically this is done:
[object setObject:test forKeyedSubscript:#"score"]; // Error: test is no object
So the solution is to put the non-object typed int into an object (boxing). You can do this with rmaddy's solution (boxed expression) or more explicit for a better understanding:
object[#"score"] = [NSNumber numberWithInt:test];

Resources