Calling C++ methods from your objective-c code - iphone

I have some C classes imported into my app. So along with my .h and .m objective-c classes I have some .h and .c C++ classes. Is it ok to do this? Or do i need to compile them into a .a so they can be used?
Assuming its all ok to do what I have done, I want to call this C++ method
mms_t *mms_connect (mms_io_t *io, void *data, const char *url, const char *host, const char *uri,const char *query,int pport, int bandwidth)
So this method returns a struct called mms_t ?
It requires I pass in some char*.
In Objective-C what can i pass in here? Are there char* in this language? I'm guessing I cant pass in a NSString in its place?
I see from a little snippet of C code
strTemp = #"mms://123.30.49.85/htv2";
char *g_tcUrl = new char[[strTemp length] + 1];
'new' is used?
Whats the objective c equivalent of the above code?
Many Thanks,
-Code

First of all, you would have to change the type of your Objective-C file to Objective-C++. You can do this by changing the file extension to .mm or by using the file info panel (ctrl-click, get info).
For char*, you can convert an NSString to a C string using either UTF8String or cStringUsingEncoding: like this:
NSString *foo = #"Foo";
char *fooascii = [foo cStringUsingEncoding:NSASCIIStringEncoding];
char *fooutf8 = [foo UTF8String];

You can freely call across Objective C and C++, in fact mix them up in virtually any combination. All you need to do is convert types where appropriate. You will need your code files to be named .mm (technically Objective C++ files) not .m files to include C++ header files.
To convert Objective C string to C style strings do:
const char *cString = [strTemp cStringUsingEncoding:NSUTF8StringEncoding];

Related

How do I set up key-value pairs for use with NSDictionary?

I want to pass a dictionary around multiple methods, with a pre-defined key set. I've seen this done in classes I've used before, but am unsure how to set this up. This is what i'd use in the m file, for example:
NSString *name = [dictionary objectForKey:kObjectsName];
NSDate *date = [dictionary objectForKey:kObjectsDate];
How do i set up the pre-determined names for the dictionary keys?
Usually Apple leaves a bunch of constants defined in the header, like for example in the NSAttributedString Application Kit Additions:
Standard Attributes
Attributed strings support the following standard attributes for text. If the key is not in the dictionary, then use the default values described below.
NSString *NSFontAttributeName;
NSString *NSParagraphStyleAttributeName;
[...]
My suggest is to use your own constants if the attributes are way too many (with define or using global const variables).
For example in the .m file (where CN is the company name):
NSString* const CNURLKey= #"URLKey";
NSString* const CNupdateTimeKey= #"updateTimeKey";
NSString* const CNtagsKey= #"tagsKey";
NSString* const CNapplicationWillTerminateKey= #"applicationWillTerminateKey";
NSString* const CNtagAddedkey= #"tagAddedkey";
NSString* const CNtagRemovedKey= #"tagRemovedKey";
NSString* const CNcolorKey= #"colorKey";
And in the header file:
extern NSString* const CNURLKey;
extern NSString* const CNupdateTimeKey;
extern NSString* const CNtagsKey;
extern NSString* const CNapplicationWillTerminateKey;
extern NSString* const CNtagAddedkey;
extern NSString* const CNtagRemovedKey;
extern NSString* const CNcolorKey;
Or you may also use define as well.
You may also make things easier for the user, making a method that return a NSArray or NSSet containing the list of all variables.
If instead you need to hold just few attributes, reconsider the choice of using a dictionary, and use a class that contains all the attributes, accessible through KVC.
You can just put #define statements in your .m file:
#define kObjectsName #"myName"
#define kObjectsDate #"myDate"
etc.

How to dynamically determine and compare the type of an objects ivars, using ivar_getTypeEncoding & #encode?

Here is the compare operation I would like to do:
// foobar is the name of an ivar on some class
// i.e. NSDate *foobar;
const char *ivarType = [self getTypeForInstanceVariableWithName:#"foobar"];
const char *objType = #encode(NSDate);
if (strcmp(ivarType, objType) == 0) {
//set value
}
NSLog(#"comparing %s with %s", ivarType, objType);
Helper method:
- (const char*)getTypeForInstanceVariableWithName:(NSString *)name {
return ivar_getTypeEncoding(class_getInstanceVariable([self class], [name cStringUsingEncoding:NSUTF8StringEncoding]));
}
NSLog result:
comparing #"NSDate" with {NSDate=#}
How come #encode returns a different type syntax than ivar_getTypeEncoding()? Is there a better way to accomplish this type determination? I must be missing something here...
Thanks!
When using ivar_getTypeEncoding() you have to pay attention to the first char. Let's see an example:
If you have a primitive type the first char will be all you get, for int it will be 'i', for char 'c', for unsigned long long 'Q', etc...
For objects and classes you might get more, like on your example, but the first character is what you want, like # for objects, # for classes, : for selectors.
You can read about those types here. You can also use constants when comparing, like _C_ID, _C_CLASS, etc. Have a loot at runtime.h.
C arrays seem to be more tricky, but I'm sure you can get around that.
One problem in your code is that you're getting the type encoding for the NSDate class, not for a NSDate object. So instead of comparing to #encode(NSDate) compare to #encode(NSDate *).
To see this type of code in action have a look at Adium's code for example.

Undefined symbols for architecture i386 with CocoaLumberjack and ZXingWidget

I've integrated the ZXing QR Code reader library (ZXingWidget) into my iPhone app, but it conflicts with a function from within the CocoaLumberjack logging library that I am also using.
Undefined symbols for architecture i386:
"ExtractFileNameWithoutExtension(char const*, signed char)", referenced from: ...
DDLog.h
NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
#define THIS_FILE (ExtractFileNameWithoutExtension(__FILE__, NO))
DDLog.m
NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy) { ...
As I call it in:
DDLogVerbose(#"%#:%#", THIS_FILE, THIS_METHOD);
The cause for this is that whichever Obj-C file contains the headers:
// import QR Code reader APIs
#import "ZXingWidgetController.h"
#import "QRCodeReader.h"
its file extension must be changed from .m to .mm for proper C++ support.
But then I lose my *DDLogVerbose(#"%#:%#", THIS_FILE, THIS_METHOD);* functionality.
What am I missing here to have these two play nice with each other?
If you're including C headers that aren't "C++-ified" into a C++ or Objective C++ file, you need to tell the compiler. Something like
extern "C" {
#include "DDlog.h"
}
in your .mms should work. Alternatively, if DDLog.h is your file, you can do something like
#ifdef __cplusplus
extern "C"
#endif
NSString *ExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
A web search for "extern C" should provide more details/examples.

Passing primitive data types by reference in Objective C

I have a C++ function which I call from Objective C.I need to pass variables by reference to the C++ function.But I get the following error in xcode - "Expected ';', ',' or ')' before '&' token in foo.h"
Function declaration in "foo.h"
#ifdef __cplusplus
extern "C"
{
#endif
NSString * LLtoUTM(double Lat,double Long,double &UTMNorthing, double &UTMEasting);
#ifdef __cplusplus
}
#endif
Function call in test_viewcontroller.m
double UTM_x;
double UTM_y;
UTMzone = [[NSString alloc] init];
UTMzone = (NSString *) LLtoUTM(latitude,longitude,UTM_y,UTM_x);
Can anyone tell me what is wrong?
Change the file to be test_viewcontroller.mm.
You told it to compile as an Objective-C file, which doesn't understand references. '.mm' means Objective-C++, which can mix the Obj-C and C++ together like what you're attempting to do.
You simply cannot do this in plain Objective-C — because references don't exist in C. They're a C++ feature. So you have to use Objective-C++, which basically means changing your Objective-C files' extensions to ".mm".

question regarding the warning that comes everywhere

Would you be able to help to delete the warning discussed below ?
I have one file example.h
In that I declared static const NSString *variable = #"cool";
Now, I have another file multiple.m. In this file I have a function Bool var2 = [object methodname:variable];
It means, I passed variable as parameter for this function, but I got warning like this:
variable is defined but not used
So,how to remove this warning?
please help me
if example.h is imported in other files aside from multiple.m, then the compiler does the check in every file it is imported into, and reports when the variable is unused in that file.
if you want to get rid of the warnings, i would change that from a static const to a macro like so:
#define Variable #"cool"
GCC won't report on unused macros.
What you should probably be doing is:
extern NSString * const variable;
in the header and then
NSString * const variable = #"cool";
in an implementation (.m) file.
(Also note where the const is; you can see this pattern in Apple's own headers as, e.g., FOUNDATION_EXPORT NSString * const NSFileTypeSocket where FOUNDATION_EXPORT is a #define for extern.)