Home > Software design >  How to pass and return an object to a C function called from iOS Swift?
How to pass and return an object to a C function called from iOS Swift?

Time:02-26

In my iOS project, I want to call a C function from my Swift code that takes an object from my Swift code and returns another object.

So far, following this tutorial and adding a little bit more stuff, I managed to call a C function that takes a simple parameter and returns a string:

  • I create the NativeLibWrapper.h file:
#import <Foundation/Foundation.h>

@interface NativeLibWrapper : NSObject

- (NSString *) sayHello: (bool) boolTest;

@end

  • I create the NativeLibWrapper.mm file:
#import <Foundation/Foundation.h>

#import "NativeLibWrapper.h"
#import "NativeLib.hpp"

@implementation NativeLibWrapper

- (NSString *) sayHello: (bool) boolTest {
    NativeLib nativeLib;
    std::string retour = nativeLib.sayHello(boolTest);
    return [NSString stringWithCString: retour.c_str() encoding: NSUTF8StringEncoding];
}

@end
  • I create the NativeLib.hpp file:

#ifndef NativeLib_hpp
#define NativeLib_hpp

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

class NativeLib
{
public:
    std::string sayHello(bool boolTest);
};

#endif /* NativeLib_hpp */

  • I create the NativeLib.cpp file:
#include "NativeLib.hpp"

std::string NativeLib::sayHello(bool boolTest)
{
    return "Hello C   : "   std::to_string(boolTest);
}
  • I add the following in Runner/Runner/Runner-Bridging-Header.h:
#import "NativeLibWrapper.h"
  • And finally, I call the C function in Swift:
NativeLibWrapper().sayHello(true)

But now, let's say that my C sayHello() function takes this kind of object as a parameter (so I can access it in the C function):

class TestAPOJO {

    var value1 = ""
    var value2 = false
}

and returns this kind of object (generated from the C function but then mapped into a Swift object, or something like that):

class TestBPOJO {

    var value3 = 0.0
    var value4 = false
}

How can I achieve that?

Thanks.

CodePudding user response:

OK so here is what I did to make it work:

  • create Objective-C TestAPOJO and TestBPOJO classes:
// TestAPOJO.h:

#import <Foundation/Foundation.h>

@interface TestAPOJO : NSObject

@property NSString *value1;
@property bool value2;

@end


// TestAPOJO.mm:

#import "TestAPOJO"

@implementation TestAPOJO

@end
  • create C TestAPOJOFromC and TestBPOJOFromC classes:
// TestAPOJOFromC.hpp:

#ifndef TestAPOJOFromC_hpp
#define TestAPOJOFromC_hpp

class TestAPOJOFromC
{
public:
    TestAPOJOFromC();
    ~TestAPOJOFromC();
    
    std::string value1;
    bool value2;
};

#endif /* TestAPOJOFromC_hpp */


// TestBPOJOFromC.cpp:

#include "TestBPOJOFromC.hpp"

TestBPOJOFromC::TestBPOJOFromC()
{
    value1 = "";
    value2 = false;
}

TestBPOJOFromC::~TestBPOJOFromC() = default;

  • in the NativeLibWrapper.h file, add:

- (TestBPOJO *) getTestPOJOS: (TestAPOJO *) testAPOJO;

  • in the NativeLibWrapper.mm file, add:
- (TestBPOJO *) getTestPOJOS: (TestAPOJO *) testAPOJO {
    NativeLib nativeLib;
    TestAPOJOFromC *testAPOJOFromC = new TestAPOJOFromC();
    testAPOJOFromC->value1 = std::string([testAPOJO.value1 UTF8String]);
    testAPOJOFromC->value2 = testAPOJO.value2;
    TestBPOJOFromC * testBPOJOFromC = nativeLib.getTestPOJOS(testAPOJOFromC);

    TestBPOJO *testBPOJO = [TestBPOJO new];
    testBPOJO.value3 = testBPOJOFromC->value3;
    testBPOJO.value4 = testBPOJOFromC->value4;
    return testBPOJO;
}
  • Related