2

I'm trying to send an NSMutableArray, or even just two strings to a function in C++ from Objective-C without success. I have no issues getting a string from C++ back to Objective-C, it's the other way around where I'm confused. Here's my code for getting a string from C++:

WrapperClass.h

#ifndef WrapperClass_hpp
#define WrapperClass_hpp

#include <stdio.h>
#include <stdlib.h>

@interface WrapperClass : NSObject
@end

@interface WrapperClass ()
- (NSString *)getHelloString;
- (NSMutableArray *)sendInfo :(NSString *)str1 :(NSString *)str2; 

// the array above is what I want to send to C++

@end

#endif /* WrapperClass_h */

WrapperClass.mm

#import <Foundation/Foundation.h>

#import "WrapperClass.h"
#include "WrapperClass.h"
#include "CppClass.h"

using namespace test;

@interface WrapperClass ()
@property (nonatomic) HelloTest helloTest;
@end

@implementation WrapperClass

- (NSString *)getHelloString {
    self.helloTest = *(new HelloTest);
    std::string str = self.helloTest.getHelloString();
    NSString* result = [[NSString alloc] initWithUTF8String:str.c_str()];
    return result;
}

- (NSMutableArray *)sendInfo :(NSString *)str1 :(NSString *)str2 {
    std::string str1 = std::string([str1 UTF8String]);
    std::string str1 = std::string([str2 UTF8String]);
    std::array<std::string, 2> myArray = {{ str1, str2 }};

// Not sure how to send to CPP ...

}

CppClass.h

#ifndef Cpp_Class_h
#define Cpp_Class_h

#include <stdio.h>
#include <string>
#include <array>

using namespace std;

namespace test {
    class HelloTest {
    public:
        std::string getHelloString();
    };
}
#endif 

CppClass.cpp

std::string test::HelloTest::getHelloString() {
    std::string outString = "Hello World!";
    return outString;
}

// this code gets the string from c++, but how to 
// send two strings or an array to a function?
2
  • This look wrong: *(new HelloTest). Hold the pointer instead. Commented Jul 7, 2020 at 13:49
  • 1
    Note that *(new HelloTest) is a memory leak in C++, and I'm assuming Objective-C++ doesn't have any special rules here. It allocates a HelloTest object on the heap, then copies it to the helloTest property, then forgets about the heap allocated object Commented Jul 7, 2020 at 13:52

1 Answer 1

2

As per my comment, hold the pointer to the C++ class:

@interface WrapperClass ()
@property (nonatomic) HelloTest* helloTest;
@end

Better still consider using std::unique_ptr<HelloTest> to manage the memory.

Add the set method in the C++ class (implementation omitted):

namespace test {
    class HelloTest {
    public:
        std::string getHelloString() const;    // Add const!
        void setHelloStrings(const std::array<std::string>& strings);
    };
}

and pass it like this from Objective-C++:

- (NSMutableArray *)sendInfo :(NSString *)str1 :(NSString *)str2 {
    std::string str1 = std::string([str1 UTF8String]);
    std::string str1 = std::string([str2 UTF8String]);
    std::array<std::string, 2> myArray = {{ str1, str2 }};
    self.helloTest->setHelloStrings(myArray);
}
Sign up to request clarification or add additional context in comments.

10 Comments

Thanks very much for answering. It makes sense what you've mentioned here, although when I try to run the code it says undefined symbols for architecture x86_64: "test::HelloTest::setHelloStrings(std::__1::array<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, 2ul> const&)", referenced from: -[WrapperClass sendInfo::] in WrapperClass.o. I've been trying to figure out why, but no luck. If you're willing I could post the code online if you have a moment.
@ctfd You need to add the implementation in CppClass.cpp.
Ah, that's what I was missing! I'm not exactly sure how to actually do that unfortunately... I currently have this. Any tips? I did have to make a couple minor changes to the syntax of self.helloTest->setHelloStrings(myArray);. It didn't like the -> for whatever reason (maybe because of the lack of implementation?), and void setHelloStrings(const std::array<std::string>& strings) had to add ..<std::string, 2>..)
@ctfd You've missed off the namespace and classname when defining the C++ set method. Also better is to use namespace test { ... } around the method definitions rather than as part of the definition signature.
@ctfd I simply mean using namespace test { ... } around the method definitions in the .cpp file like you did with the declarations in the .h file.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.