Returning Typed Pointer From Swift to C++

I have a struct defined in Swift, i want to pass it's instance pointer from swift to C++. When I am trying to directly return Typed Pointer from Swift Function to C++, the function doesn't get expose to C++.

Code which i have tried.

// Defined Structure 

public struct MyStruct {
    
    public init (_ pValue : Int) {
        
        uValue = pValue
    }
    public var uValue : Int
}

var my_struct = MyStruct(20)

// Function which returns Struct Pointer to C++
// When I return typed pointer this function doesn't get exposed to C++
public func PassStructPointer () -> UnsafeMutablePointer<MyStruct> {
    
    withUnsafeMutablePointer(to: &my_struct) { pointer in
        
        return pointer
    }
}

But when I pass UnsafeRawMutablePointer instead of type pointer then the function does get expose to C++

var my_struct = MyStruct(20)

// This get expose to C++.
public func PassStructPointer () -> UnsafeMutableRawPointer {
    
    return withUnsafeMutableBytes(of: &my_struct) { pointer in
        return pointer.baseAddress!
    }
}

Can we not pass typed pointer of the types defined by us?

Warning: Do not store or return the pointer for later use.

withUnsafeMutablePointer(to:_:)
The pointer argument to body is valid only during the execution of withUnsafeMutablePointer(to:_:). Do not store or return the pointer for later use.

1 Like

In general what you are asking for here doesn't make sense. Most swift structs do not have stable addresses. You cannot "take the address" of a typical object in Swift and expect to return it from a function and have it still reference the same value (more fundamentally, this is because structs are values, and do not have identity; you can't have the "same struct value" any more than you can have "the same 4").¹ Swift is not just "C[++] with different spelling". It has a fundamentally different model of objects and memory, and you must adhere to its rules. When interoperating between Swift and C[++], you must have a pretty clear understanding of the memory models of both languages.

You can create a pointer to a struct that's scoped to a closure like the argument of withUnsafeMutablePointer. The pointer created by that function and passed to body is guaranteed to be valid for the duration of the call to body, but no longer. Returning the pointer from body is a constraint violation and will not work.

It is possible to construct objects with stable memory addresses, usually using manual memory allocation (UnsafePointer<T>.allocate(capacity:)).


¹ the problem is more-or-less analogous to (but not exactly the same as) what you would have if you wrote the following in C++:

int *func(int x) { return &x; }

the pointer created in the function body is only valid within the scope of the function body--it cannot be returned from the function body scope.

12 Likes

Yeah I got that that the pointer is valid within the scope of the closure and one should not return it or use it outside the scope.
I want to understand how can we pass a typed value type as a reference to c++ Function as an input parameter.

See this ancient post by @eskimo.

Basically, you declare the struct in C and import it into Swift.

@main
enum CallC {
    static func main () {
        var b = bar (value: 7)
        print_bar (b)
        print (b)
        mutate_bar (&b)
        print (b)
    }
}
print_bar 7
bar(value: 7)
mutate_bar 7
bar(value: 13)
// Bridging-Header.h
//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//

#include "C.h"

//  C.h

#ifndef C_h
#define C_h


struct bar {
    long value;
};

void print_bar (const struct bar);
void mutate_bar (struct bar*);

#endif /* C_h */

//  C.c

#include <stdio.h>
#include "C.h"

void print_bar (const struct bar v) {
    printf ("%s %ld\n", __func__, v.value);
}
void mutate_bar (struct bar *pv) {
    printf ("%s %ld\n", __func__, pv->value);
    pv->value = 13;
}

Similarly for C++, but you export the C++ functions as C functions.

Hi ibex, you have misunderstood the question. I want to pass pointer of Struct defined in Swift to C++/C not from C++/C to swift. So can you suggest a way for that.

That may prove to be not a trivial task. :slight_smile:

I urge you to read the language interoperability guides, which @eskimo has provided, quoted below.