Search code examples
cflutterdartdart-ffi

Problem Getting Float Pointer and Int from Native C to Dart


I have a basic FFI call that retrieves a C struct from Dart. Only the char * and int * fields of the struct are returning proper values. The float * and int are returning the wrong values. The C and Dart code is below along with the output. If I were to print the two bad types out on the C side, they do yield proper values.

C Code

// C code
typedef struct {
    float * floatPtr;
    int count;
    char * name;
    int * intPtr;
}baseStruct;


baseStruct getMyStruct(){
    static baseStruct myStruct;
    static int someint = 22;
    static float foo [] = {0.1, 0.2, 0.3};
   
    myStruct.floatPtr = foo;  
    myStruct.count = 0;
    myStruct.intPtr = &someint;
    myStruct.name = "some string";
    
    return myStruct;
}

Dart Code

// Dart Type for C struct
class MyStructType extends Struct {
  
  external Pointer<Float> floatPtr;
  @Int32()
  external int count;
  external Pointer<Int> intPtr; //worked 
  external Pointer<Utf8> name; //worked

}

// type defs for FFI
typedef GetMyStructNative = MyStructType Function();
typedef GetMyStruct = MyStructType Function();


// Code to call function from dynamic library 
static final getMyStruct  = module
.lookupFunction<GetMyStructNative, GetMyStruct>('getMyStruct');


// call native function and get native struct
MyStructType myStruct = getMyStruct();

/***************************** OUTPUT *************************/
final count = myStruct.count;
print("count: $count"); // prints some big number like 475423 that's not 0 (incorrect)

final intPtr = myStruct.intPtr.value;
print("count: $intPtr"); // prints 22 (correct)

final name = myStruct.name.toDartString();
print("name: $name");  // prints 'some string' (correct)

final floatPtr myStruct.floatPtr.asTypedList(3);
print("floatPtr: $floatPtr"); // prints  [0.0, 0.0, 4.764414778704378e-44] (incorrect)

Solution

  • Got this answer from @blaugold on github. The order of the fields in the structs must match. So changing the dart struct as below fixes the problem.

    class MyStructType extends Struct {
      external Pointer<Float> floatPtr;
    
      // Int32 -> Int
      @Int() 
      external int count;
    
      // The order of fields matters, so `name` and `intPtr` need to be flipped.
      external Pointer<Utf8> name;
      external Pointer<Int> intPtr;
    }