Home > OS >  Calling C function from Swift shows different results in CLion than in Xcode
Calling C function from Swift shows different results in CLion than in Xcode

Time:06-01

I am trying to call a C function from Swift , but I do not know exactly how to define variables to pass parameters. This is the function declaration:

/* Function Declarations */
extern void compute_feature_set(const double input[11025],
                                double M_data[], int M_size[2],
                                double D_data[], int D_size[2],
                                double DD_data[],
                                int DD_size[2],
                                double VT[10], double *mp,
                                double r_42[42], double *fM);

The data is an array of floats. So I tried ​​:

    let s = data.compactMap{ Double($0)}
    
    var mSize = Array<Int32>(repeating:Int32(0.0), count:2)
    var dSize = Array<Int32>(repeating:Int32(0.0), count:2)
    var dD_Size = Array<Int32>(repeating:Int32(0.0), count:2)
    
    var mData =  Array<Double>(repeating:0.0, count:48)
    var dData =  Array<Double>(repeating:0.0, count:48)
    var dD_Data =  Array<Double>(repeating:0.0, count:48)
    
    var vt =  Array<Double>(repeating:0.0, count:10)
    var mp =  Double(0.0)
    var r  = Array<Double>(repeating:0.0, count:42)
    var fM = Double(0)

    compute_feature_set(s, &cout, &mSize, &vx, &dSize, &dD_Data, &dD_Size, &vcta, &mp, &r, &fM)

When I run the code in Clion with the following function it works fine and the output matches the expected values:

static void main_compute_feature_set(void)
{
    static double dv[11025];
    double DD_data[48];
    double D_data[48];
    double M_data[48];
    double r_42[42];
    double VT[10];
    double fM;
    double mp;
    int DD_size[2];
    int D_size[2];
    int M_size[2];
    /* Initialize function 'compute_feature_set' input arguments. */
    /* Initialize function input argument 'input'. */
    /* Call the entry-point 'compute_feature_set'. */
    argInit_11025x1_real_T(dv);
    compute_feature_set(dv, M_data, M_size, D_data, D_size,
                      DD_data, Dd_size, VT,
                      &mp, r_42, &fM);
}

However, when I run my implementation in Swift, I get very different results.

CodePudding user response:

You could try passing pointers of the Arrays, rather than the Arrays directly.

Using Imported C Functions in Swift | Apple Developer Documentation

Call Functions with Pointer Parameters

Whenever possible, Swift avoids giving you direct access to pointers. When importing C function parameters, however, Swift maps pointer parameters to standard library pointer types.
The following tables use Type as a placeholder type name to indicate syntax for the mappings.

For return types, variables, and arguments, the following mappings apply:

C Syntax Swift Syntax
const Type * UnsafePointer<Type>
Type * UnsafeMutablePointer<Type>

double[] is pretty much equivalent to double * in this case.

CodePudding user response:

Looks like the problem with your code is passing data to your function. You use compactMap to make an Array of Double and then pass the pointer of this array. But Array and Double are struct in Swift so you pass the pointer of struct with structs instead of array of double values.

To convert your data to array of bytes you should use withUnsafeBytes e.g.:

Swift:

let data = Data([0xaa, 0xbb, 0xcc, 0xdd])
data.withUnsafeBytes {
    passData($0)
}

C/ObjC:

void passData(const double input[11025]) {
    NSLog(@"%x", input[0]); // Prints: ddccbbaa
}
  • Related