wrapping C++ std::strings in Objective-C/C++

What's the best way of wrapping C++ strings in Objective-C/C++? I tried using NSStrings with pointers (NSString*) but i'm having memory issues as it's throwing EXC_BAD_ACCESS issues at the compiler level during runtime. Using ObjC++ double to C++ double for my numerical data seemingly works fine but the strings are proving to be a huge headache. I've seen a few ways of doing this but none were very clear.


Included are the Objective-C++ files I'm using.


TestObjC.h

#import <Foundation/Foundation.h>
@interface TestObjC : NSObject
- (double) TestCPP: (double) A : (double) B : (double) C :(double) D : (double) E : (double) F : (NSString*) Caller : (NSString*) Sector : (NSString*) OutPut;
@end


TestObjC.mm


#import “TestObjC.h”
#import “TestCPP.h"
@interface TestObjC(){
    Test wrapped;
}
@end

NSString *Caller  = Caller;
string Call = [Caller UTF8String];
NSString *Sector = Sector;
string Sect = [Sector UTF8String];
NSString *OutPut  = OutPut;
string OP = [OutPut UTF8String];

@implementation TestObjC
- (double) TestCPP: (double) A : (double) B : (double) C :(double) D : (double) E : (double) F : (NSString*) Caller : (NSString*) Sector : (NSString*) OutPut;
@end
return wrapped.TesterFunction((double) A, (double) B, (double) C, (double)D, (double)E, (double) F, Call, Sect,OP);
}
@end

Your code shown as TestObjC.mm is broken.

Create a buildable code and copy it without modification.

I included a dummy .cpp and .h just to better mimic my code


My real issue is whether or not there's an easier way to to the NSString to std::string conversion. I would prefer to avoid pointers and I think the examples I've seen out there are not very clear or focused on void functions with single parameters.



TestObjC.h



#ifndef TestObjC_h
#define TestObjC_h
#import <Foundation/Foundation.h>
@interface TestObjC : NSObject
- (double) TestCPP: (double) A : (double) B : (double) C :(double) D : (double) E : (double) F : (NSString*) Caller : (NSString*) Sector : (NSString*) OutPut;
@end
#endif / TestObjC_h */


TestObjC.mm



#import "TestObjC.h"
#import "TestCPP.h"
@interface TestObjC(){
    Test wrapped;
}
@end
NSString *Caller  = Caller;
string Call = [Caller UTF8String];
NSString *Sector = Sector;
string Sect = [Sector UTF8String];
NSString *OutPut  = OutPut;
string OP = [OutPut UTF8String];
@implementation TestObjC
- (double) TestCPP: (double) A : (double) B : (double) C :(double) D : (double) E : (double) F : (NSString*) Caller : (NSString*) Sector : (NSString*) OutPut;
{
return wrapped.TesterFunction((double) A, (double) B, (double) C, (double)D, (double)E, (double) F, Call, Sect,OP);
}
@end


TestCPP.h


#ifndef TestCPP_h
#define TestCPP_h
#include <iostream>
#include <string>
using namespace std;
class Test
{
  
public:
  
    double
    TesterFunction(
        double A,
        double B,
        double C,
        double D,
        double E,
        double F,
        string Call,
        string Sect,
        string OP);
};
#endif / TestCPP_h */


TestCPP.cpp


#include "TestCPP.h"
double Test::TesterFunction(double A, double B, double C, double D, double E, double F, string Call, string Sect, string OP)
{
   
    if (Call == "Call" && OP == "Value" && Sect == "Poli")
    {
        return(A*B+C-D/E+F);
    }
    else if (Call == "Bin" && OP == "Value" && Sect == "Econ")
    {
        return(A*B+C-D/E-F);
    }
    /
    else if (Call == "Call" && OP == "Value" && Sect == "Sci")
    {
        return(A+B+C-D*E/F);
    }
    else if (Call == "Bin" && OP == "Value" && Sect == "Econ")
    {
        return(A*B*C*D*E*F);
    }
   
    return 88888888;
   
}

As far as C++ is concerned, the NSString * is a void pointer. That's why you see all of the examples focused on void pointers.


So, no, there are no supplied conversions between NSString and std::string. If your code is crashing, it's likely because somewhere along the line you're trying to pass the NSString pointer to something expecting a character pointer.

Accepted Answer

With your fixed codes, I can eliminate many minor possibilities. Thus I can definately say, what is bad with your code is:

NSString *Caller  = Caller;
string Call = [Caller UTF8String];
NSString *Sector = Sector;
string Sect = [Sector UTF8String];
NSString *OutPut  = OutPut;
string OP = [OutPut UTF8String];

In Objective-C, outside of @interface ... @end or @implementation ... @end is under global context.

You are declaring global variables which have no relationship with the parameters of your method `TestCPP:::::::::` .

And the three NSString variables, they are initilized with non-initialized themselves.

(I am a little astonished with seeing Clang compiles this sort of initializations with no warnings.)


So, the variables are very probably NULLs, so method calls in Objective-C like [Caller UTF8String] generates NULLs. I believe you cannot initialize std::string with NULL.

Moving the 6 lines to inside the `TestCPP:::::::::` method would work. But if your main concern is bridging between C++ and Swift, I recommend you to use const char* for an intermediate type when bridging Swift.String to std::string .


Try this.


TestObjC.h


#ifndef TestObjC_h
#define TestObjC_h
#import <Foundation/Foundation.h>
@interface TestObjC: NSObject
- (double) testCPP:(double)a :(double)b :(double)c :(double)d :(double)e :(double)f :(const char*)caller :(const char*)sector :(const char*)outPut;
@end
#endif /* TestObjC_h */


TestObjC.mm


#import "TestObjC.h"
#import "TestCPP.h"
@interface TestObjC(){
    Test wrapped;
}
@end
@implementation TestObjC
- (double) testCPP:(double)a :(double)b :(double)c :(double)d :(double)e :(double)f :(const char*)caller :(const char*)sector :(const char*)outPut
{
    string Call(caller), Sect(sector), OP(outPut);
    return wrapped.TesterFunction(a, b, c, d, e, f, Call, Sect,OP);
}
@end


And call it from Swift like this:

let objCObj = TestObjC()
let test = objCObj.testCPP(200.00,210.00,0.25,0.15,0.0025,0.02,"alpha","bravo","charlie")

Thanks! that worked perfectly. const char* is a great simple solution to what seems like a complex problem.

wrapping C&#43;&#43; std::strings in Objective-C/C&#43;&#43;
 
 
Q