我试图将结构数组从C++代码返回到Swift代码。

SWIFT代码:

struct CPoint {
    let x: CDouble
    let y: CDouble
}

struct CStruct {
    let p1: CPoint
    let d: CDouble
    let p2: CPoint
    let i: CInt
}

func get_structs() {

    let cnt = ... //Getting size from c++ code
    var buf = [CStruct](count: cnt, repeatedValue: CStruct(p1: CPoint(x: 0, y: 0), d: 0, p2: CPoint(x: 0, y: 0), i: 0))
    let addr = UnsafeMutableBufferPointer(start: &buf, count: buf.count).baseAddress
    get_structs_c(addr)

    for cstruct in buf {
        //First cstruct is OK. Next are corrupted.
    }
}

C++代码:
typedef struct Point {
    double x;
    double y;
}

typedef struct Struct {
    Point p1;
    double d;
    Point p2;
    int i;
}

void get_structs_c(void *buf) {
    Struct * structs = (Struct *) buf;
    const std::vector<const Struct *> vec = ... // getting values no matter from where
    for (int i = 0; i < vec.size(); i++) {
        const Struct * s = vec.at(i);
        structs[i] = Struct{ s->p1, s->d, s->p2, s->i};
    }
}

代码很简单,但是结果将损坏的值保存到buf

但是,如果我从iCStruct中删除Struct字段,则它将返回正确的值,或者如果我将i的类型从CIntint更改为CDoubleDouble,那么还将返回正确的值。因此,可能与int桥接有关的一些问题。

我检查了CStructStruct的大小,它似乎是相同的44个字节。

任何帮助表示赞赏,在此先感谢!

UPD 1:仅当struct的大小与8个字节成比例时才可以正常工作。

UPD 2:我检查了内存寻址,发现swift的sizeof告诉我
struct CStruct {
    let p1: CPoint
    let d: CDouble
    let p2: CPoint
    let i: CInt
}

大小为 44 字节,但&struct [1]-&struct [0] = 48 !

如果以较差的方式对结构字段进行重新排序:
struct CStruct {
    let i: CInt
    let p1: CPoint
    let d: CDouble
    let p2: CPoint
}

然后它会自动对齐,sizeof的大小为48,并且可以正常工作。

这样的默认不兼容性正常吗?

最佳答案

您的get_structs_c函数本质上是危险的,因为您没有传入缓冲区的大小,因此这是缓冲区溢出漏洞!您真正需要的是这样的签名:

 struct StructList {
    Struct* items;
    size_t size;
 };

 StructList* CreateAndTransferOwnershipFromC();

要么:
 size_t CopyFromC(Struct* output_buffer, size_t buffer_size);

这里最有可能发生的是C++和Swift版本之间的大小不匹配,其中某些缓冲区未满或您正在超载缓冲区。

否则,您可能会遇到alignment问题。一个更安全(但可能效率较低)的解决方案是将数据编码成二进制编码的字符串(例如protocol buffers),以使其更容易保证两端的二进制兼容性。否则,您可能需要使用GCC compiler directives之一进行对齐/打包以确保其正确。

关于c++ - 从C++传递结构数组到Swift,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31496905/

10-11 22:41
查看更多