Passing NSString* to a C++ reference parameter - c++

Have an Objective-C++ function. (The file has the correct .mm extension).
int SPGetNumericAttribute(NSMutableString* line, NSString* &attr) {...}
Some code calls as follows:
NSString* queryAttr = nil;
int res = SPGetNameAttribute(line, queryAttr); <-- error
Compiler complains:
No matching function call for 'SPGetNameAttribute'.
Is there a technical reason why you can't pass an Objective-C object to a C++ reference parameter?
My guess is something to do with ARC.

ARC needs to know how to handle the reference counting of the second parameter inside of the function. By default the parameter has autoreleasing type. Thus your variable queryAttr must have the autoreleasing ARC type
__autoreleasing NSString* queryAttr = nil;
or alternatively you can declare your function as
int SPGetNumericAttribute(NSMutableString* line, NSString* __strong &attr) { ... }
and the error disappears for strong variables. Tests with Instruments show that ARC seems to be handling this right, too. But then you may only use strong variables for this parameter.
I think it should be better, if you use a pointer instead:
int SPGetNumericAttribute(NSMutableString* line, NSString** attr) { ... }

Related

how to deal with a function pointer problem?

i'm implementing a normal function pointer.
so this is the function that i want to call:
WndDyn* Punkt2d::pEditPunkt(WndInfo& wi, Int32 AnzSichtChar, Bool WithUnit,
const DecimalsConf& DecConf)
{
WynDyn_callback Dyncallback;
Dyncallback.AnzSichtChar = AnzSichtChar;
Dyncallback.WithUnit = WithUnit;
Dyncallback.DecConf = DecConf;
return &(DlgZeile(wi)
+ pEditAll(Dyncallback, &pEditFeldX)//pEditFeldX(AnzSichtChar, WithUnit,
DecConf)
+ FntXUnit(2)
+ pEditFeldY(AnzSichtChar, WithUnit, DecConf)
);
}
After defining the function that needs to be called i defined my callee as follow:
WndDyn* pEditAll(WynDyn_callback& Dyncallback, WndDyn* (func_Call)
(WynDyn_callback)) {
return func_Call(Dyncallback);
}
And last of all this is the function that needs to be called using the callee function:
WndDyn* Punkt2d::pEditFeldX(WynDyn_callback Dyncallback) {
return &Edit(pNewStrDataLink(m_x, DLUC_Length, Dyncallback.DecConf),
Dyncallback.AnzSichtChar)
.WithSelAllOnFocus(True);
}
My actuall problem is that my compiler is underlining the function pEditFeldX
in this line pEditAll(Dyncallback, pEditFeldX) in the function pEditpunkt and showing me this Error:
Severity Code Description Project File Line Suppression State
Error C3867 'Punkt2d::pEditFeldX': non-standard syntax; use '&' to
create a pointer to member
Severity Code Description Project File Line Suppression State Error
(active) E0167 argument of type "WndDyn (Punkt2d::)(WynDyn_callback
Dyncallback)" is incompatible with parameter of type "WndDyn
()(WynDyn_callback)"
Because pEditFeldX is a member function you can't just call pEditFeldX(Dyncallback). You must call the function on some Punkt2d object, using e.g. meinPunkt2d.pEditFeldX(Dyncallback).
If you write pEditFeldX(Dyncallback) inside the Punkt2d class then it means (*this).pEditFeldX(Dyncallback). The compiler adds (*this). to save some typing.
A function pointer only points to a function. It doesn't point to a function and an object. It points to pEditFeldX, not meinPunkt2d.pEditFeldX. You must specify the Punkt2d object when you call it.
To remember that a Punkt2d must be specified, a function pointer which points to a member function is declared as this: WndDyn* (Punkt2d::*func_Call)(WynDyn_callback) and called as this: meinPunkt2d.*func_Call(Dyncallback);
If the function pointer is &pEditFeldX then meinPunkt2d.*func_Call(Dyncallback) is the same as meinPunkt2d.pEditFeldX(Dyncallback)
This doesn't apply to static member functions. Static member functions can be used with normal function pointers since no object is required.
It is not quite clear what you are trying to do, but if I understand it right, I think that std::function would be able to solve your problem std::function is able to store anything which can be called, including "half of a function call" like you seem to want. std::bind can make these "half function calls".
You could use them like this:
// in pEditPunkt
pEditAll(Dyncallback, std::bind(&CPunkt2d::pEditFeldX, this, std::placeholders::_1))
// in pEditAll
WndDyn* pEditAll(WynDyn_callback& Dyncallback, std::function<WndDyn* (WynDyn_callback)> (func_Call)
(WynDyn_callback)) {
return func_Call(Dyncallback);
}
First of all i would like to thanks #user253751 for his patient and great support. i would like to share with you how my code look like now:
#include <functional>
// pointer function
WndDyn* pEditAll(WynDyn_callback& Dyncallback, std::function<WndDyn*
(K_WynDyn_callback)>func_Call) {
return func_Call(Dyncallback);
}
//the calle
WndDyn* K_Punkt2d::pEditPunkt( WndInfo& wi, Int32 AnzSichtChar,
Bool WithUnit, const DecimalsConf& DecConf)
{
WynDyn_callback Dyncallback;
Dyncallback.AnzSichtChar = AnzSichtChar;
Dyncallback.WithUnit = WithUnit;
Dyncallback.DecConf = DecConf;
return &(DlgZeile(wi)
+ pEditAll(Dyncallback,
std::bind(&Punkt2d::pEditFeldX, this,
std::placeholders::_1))//pEditFeldX(AnzSichtChar, WithUnit,
DecConf)
+ FntXUnit(2)
+ pEditFeldY(AnzSichtChar, WithUnit, DecConf)
);
}

Pointer in function argument seems not working

I'm developing in C++. I have 2 objects : which are the StandaloneAgent and the ConfigManager.
I want from the Standalone Agent to reach a char * variable in the ConfigManager with a function .
int32_t StandaloneAgent::getConfigFile(char * file){
int32_t code = mConfigMgr->getConfigFile(file);
return code;
}
int32_t ConfigManager::getConfigFile(char * file){
file = mConfigFile;
return 0;
}
Here, the ConfigManager objet is an attribute of the StandaloneAgent with the
ConfigManager * mConfigMgr; variable.
And the file I want to reach is located in the mConfigFile attribute of the ConfigManager.
The problem is :
While putting std::cout,
the mConfigFile in the is OK and
the file variable after the
file = mConfigFile;
is OK
But when I return in the getConfigFile() function of the standalone agent, the file variable is a null pointer and I don't know why.
Is there a C++ specification that I am missing ?
Arguments to functions are either passed by-value or by-reference. Any variable passed by-value will be local to the function and any changes made to it is local to the function too. This means that when to assign a new value to the pointer (file = mConfigFile) you only change the pointer in the function. The pointer you passed as an argument is unaffected.
When taking arguments by-reference, the variable inside the function references the variable used to call the function. Any changes made to that variable will be directly made to the variable used in the call to the function.
In your case, that means that you need to change the ConfigManager::getConfigFile function:
int32_t ConfigManager::getConfigFile(char*& file){
file = mConfigFile; // the change is made to the variable used as an argument
return 0;
}
If the pointer passed to StandaloneAgent::getConfigFile is also supposed to be changed (I assume it is), you need the same change there:
int32_t StandaloneAgent::getConfigFile(char*& file){
int32_t code = mConfigMgr->getConfigFile(file);
return code;
}

Was it possible to get a pointer to member from an instance of an object?

I was porting some legacy code to VS 2015 when this compiler error halted the build:
error C3867: 'OptDlg::GetFullModel': non-standard syntax; use '&' to create a pointer to member
Going to the corresponding file and line, I saw this:
Manager mgr = GetDocument()->GetManager();
OptDlg dlg;
...
mgr->SetFullModel(dlg.GetFullModel);
if ( dlg.GetFullModel )
mgr->SetSymm(...
GetFullModeland SetFullModel are the getter/setter pair for a member variable in two different classes:
class Manager {
...
bool GetFullModel() { return m_bFullModel; }
void SetFullModel(bool bFlag) { m_bFullModel = bFlag; }
....
};
class OptDlg {
...
void GetFullModel() { return m_bFullModel; }
void SetFullModel(bool bValue) { m_bFullModel = bValue; if ( bValue ) m_bInside = 0;}
Yep, something's wrong. Was dlg.GetFullModel supposed to be a pointer to a member function? I thought those use the class name, not an instance. Not to mention what that would mean for execution semantics...
C++ is still relatively new to me, so I tried Google. It had a lot on function pointers, but they all looked different from what I had:
&OptDlg::GetFullModel // Standard-compliant
vs
OptDlg::GetFullModel // The "normal" way to mess up getting a pointer to member, it seems
vs
dlg.GetFullModel // ?
Is dlg.GetFullModel just another way of getting a pointer to member function? If not, what is the "standard C++ version", if there is one? Is this just another one of those VS 6 "extensions"?
&OptDlg::GetFullModel // Standard-compliant
If your parameter types were supposed to be taking member functions, that's what you'd use. But they take booleans. It looks like you're just missing parentheses on your function calls, and it should be:
mgr->SetFullModel(dlg.GetFullModel());
if (dlg.GetFullModel())
mgr->SetSymm(...
Probably someone was ignoring warnings (or didn't have them on) and hence a pointer value (being produced through whatever shady means) was always being interpreted as non-NULL, hence boolean true.
Is this just another one of those VS 6 "extensions"?
It would appear to be the case, although this comment is the only documented evidence I can find it was an intentional/advertised "feature". Don't see any formal announcement of it being added or taken out.
It strongly looks to me like someone mis-typed dlg.GetFullModel() (which would call the function), not that they were trying to get a member function pointer.
Presumably the legacy compiler let it slide, taking the address of the function without using & and converting the non-null function pointer to bool (with value true) to pass into the set function.

How to avoid deprecated conversion from string constant to 'char*' in C++

I would like to call the following code in C++, which I cannot change:
void getAge(char *name)
{
// do something
}
When I call it with getAge("hello");, it has the following warning:
warning: deprecated conversion from string constant to 'char*'
but there is no warning in C code. What is the difference, and how do I change the call to avoid the warning in C++?
the function […] can not be changed
Then write a wrapper around the function and copy the string – or, if you feel lucky (= you know that the string won’t be modified inside the original function), explicitly cast away const-ness:
void getAge(char const* name) {
the_namespace::getAge(const_cast<char*>(name));
}
If you’re unsure whether the function modifies its parameters, use something like the following – however, if that’s the case then calling the function with a string literal (getAge("hello")) would have been invalid anyway.
void getAge(char const* name) {
std::string buffer(name);
the_namespace::getAge(&buffer[0]);
}
Here we copy the string into a modifiable buffer and pass an address to its first character to the original function.
The safest way is to copy the string, then call the C function:
void getAgeSafe(const char* name)
{
std::vector<char> tmp = name?
std::vector<char>(name, name+1+strlen(name))
:std::vector<char>();
getAge( tmp.data() );
}
and call getAgeSafe from your C++ code.
A less safe way that relies on the C code never modifying the char* name would be to const_cast, again in a "wrapping" function:
void getAgeUnsafe(const char* name)
{
getAge( const_cast<char*>(name) );
}
but this time the name is more scary, as is the operation. If you call getAge with a compile time constant string like "bob", if getAge modifies its input, undefined behavior results (this is true in both C and C++ -- C++ at least warns you about it).
You can try getAge((char*)"hello").
In c++ you can write it like this,
void getAge(string name)
{
// do something
}
and also include the header file #include<string> because you are using string now

Convert Objective C "code blocks" to equivalent in C++

I need a help on converting some Objective C "code block" methods to the equivalent in C++.
Please advise.
A is being used as code block...
Defined in .h file..
typedef void (^A)(void*); //argument is ptr to B
Used in one .mm file..
[[hello getInstance] getB]->queueLoadImageWithBlock([self.str UTF8String], (A
)^(void* img)
{
//some code...
});
The most direct analogy is std::function. This is a value type that is given a signature (e.g. std::function<int(int)> and can be any function object of the appropriate signature. A lambda can be used in place of the block at the call site.
obj->queueLoadImageWithBlock(self.url, [](void* img)
{
UIImage* img2 = (UIImage*)img;
UIImageView* iv = [[UIImageView alloc] initWithImage:img2];
iv.backgroundColor = [UIColor clearColor];
[self.iconSlot addSubview:iv];
iconLoaded(iv);
[iv release];
});
With Apple's version of clang you can use blocks in C and C++ as well as Objective-C. This is non-standard C++, obviously, but it works.
You can use C++ lambdas without changing the called function since lambdas are assignable to blocks (but not the other way around). See this question for more information.
As long as the requirement for a block is yours as opposed to system.
Like I said, there are several approaches. The function pointers require the least boilerplate, but they need an extra argument to pass the context from the caller (the self stuff in your case). Functors and pointer-to-members typically require template machinery to work, let's not go there. So with a function pointer, here's how it would go:
//Let's define a callback datatype
typedef void (*ResourceLoadObjFuncPtr)(void *, void*);
//argument 1 is ptr to ResourceLoadDescriptor, argument 2 is iconSlot, whatever it is
//Function that implements that type:
void MyLoad(void *img, void *iconSlot)
{
UIImage* img2 = (UIImage*)img;
UIImageView* iv = [[UIImageView alloc] initWithImage:img2];
iv.backgroundColor = [UIColor clearColor];
[(TheTypeOfIconslot*)iconSlot addSubview:iv];
iconLoaded(iv);
[iv release];
}
And you'd have to modify the prototype of queueLoadImageWithBlock to accept a ResourceLoadObjFuncPtr parameter instead of ResourceLoadObjCBlockCB, and another parameter for the context (just the iconSlot in our case).
And invoke:
[[GameViewController getInstance] getResourceLoadMediator]->
queueLoadImageWithFunction([self.url UTF8String], MyLoad, self.iconSlot);
Blocks are closures - they capture the variables of the function where they're declared. C++ provides no closures that GCC on iOS supports (other than, well, blocks). So you'd have to pass the variables from the function scope to the function parameter by hand. In our case, if my assumptions are right, there's just one variable; in a more complex case, you'd have to wrap them in a structure and pass a pointer to one.
An alternative to that would be using an abstract base class and a concrete implementation that captures the context via its constructor. This would go like this:
//Callback type
class ResourceLoader
{
public:
virtual void Load(void *) = 0;
};
//A callback implementation - not a function, but a class
class MyResourceLoader : public ResourceLoader
{
IconSlotType *iconSlot;
void Load(void *img)
{
//Same loader stuff as above
}
public:
MyResourceLoader(IconSlotType *isl)
:iconSlot(isl)
{}
};
The queueLoadImageWithBlock equivalent would now take a second parameter of type ResourceLoader* and no third parameter. As for the invokation, there's the issue of callback object lifetime. Is queueLoadImageWithBlock asynchronous - that is, does it return before invoking the callback? If so, then a local instance of MyResourceLoader won't do, you'd have to create one dynamically and somehow dispose it. Assuming it's synchronous (i. e. does not invoke the callback after it returns):
MyResourceLoader ResLoader(self.iconSlot);
[[GameViewController getInstance] getResourceLoadMediator]->
queueLoadImageWithLoader([self.url UTF8String], &ResLoader);
If it's not:
[[GameViewController getInstance] getResourceLoadMediator]->
queueLoadImageWithLoader([self.url UTF8String], new MyResourceLoader(self.iconSlot));