1

I'm learning how to use dart ffi.

I don't have much C experience or knowledge.

I'm trying to call a function from a C library(tiny file dialogs).

I can call other functions however I can't call this one

char * tinyfd_saveFileDialog(
        char const * aTitle , /* NULL or "" */
        char const * aDefaultPathAndFile , /* NULL or "" */
        int aNumOfFilterPatterns , /* 0 */
        char const * const * aFilterPatterns , /* NULL or {"*.jpg","*.png"} */
        char const * aSingleFilterDescription ) /* NULL or "image files" */
{

the main issue is that I don't understand what

char const* const * a FilterProperties, / *Null or {"*.jpg", "*.png"} */

means.

As far as I was able to get from this issue the C function is asking for an array of strings. The arg aNumberOfFilterPatterns defines the length of the array.

If that's the case, how can I prepare the array in dart to pass it to C?

xerotolerant
  • 1,955
  • 4
  • 21
  • 39

1 Answers1

2

I was able to do it by making a pointer to pointer to char

like this

/// Define the type like this
typedef SaveFileDialogD = Pointer<Utf8> Function(
 
  Pointer<Pointer<Utf8>> listOfStrings,

);

Look up the function in the dynamic library


SaveFileDialogD saveFileDialog = dylib
    .lookupFunction<SaveFileDialogC, SaveFileDialogD>('dylib');

make a function to convert Dart list of string to something more C friendly

/// Don't forget to run malloc.free with result!
Pointer<Pointer<Utf8>> strListToPointer(List<String> strings) {
  List<Pointer<Utf8>> utf8PointerList =
      strings.map((str) => str.toNativeUtf8()).toList();

  final Pointer<Pointer<Utf8>> pointerPointer =
      malloc.allocate(utf8PointerList.length);

  strings.asMap().forEach((index, utf) {
    pointerPointer[index] = utf8PointerList[index];
  });

  return pointerPointer;
}

Finally call the C function like this

Pointer<Utf8> result;
    final strListPointer = strListToPointer(["one", "two", "three"]);

    result = saveFileDialog(
       strListPointer;
    );
xerotolerant
  • 1,955
  • 4
  • 21
  • 39
  • When using `utf8PointerList.length` in `malloc.allocate()` my app is crashing with `malloc(): invalid size (unsorted)`. The docs are saying that allocate() expects byteCount of bytes as first argument. Is `utf8PointerList.length` the right size to allocate? – roman May 03 '22 at 12:23
  • 1
    There's also a `sizeOf()` function in dart::ffi. I changed the allocate() call to the following - `malloc.allocate(sizeOf>() * utf8PointerList.length);`. Now the issue seems to be resolved. – roman May 03 '22 at 12:33
  • Hey, I'm not sure sorry. I never ended up using `malloc` as part of my program. – xerotolerant May 03 '22 at 21:20
  • And what did you use instead of malloc? – roman May 04 '22 at 11:58
  • I never had reason to use malloc. My understanding of malloc is that is for allocating and deallocating memory. Dart is a memory managed language so you'll never really need to use malloc normally. FFI is sort of a bridge that you use to access C libraries. I never had to use any C specific techniques. Just use native dart objects. Use FFI specific objects just to communicate with C libraries. if you need more help we could chat so I can better understand your problem. – xerotolerant May 04 '22 at 15:43
  • I'm also calling a C function from Dart(Flutter). The function in C is expecting an array of char* as parameter (similar to the standard `int main(int argc, char** argv)`. I think your answer is already showing most of the steps on how to do it. The only thing that's missing is allocating correct size using `sizeOf` and cleaning the allocated pointers once you're done with them. Thank you for your help. – roman May 09 '22 at 08:52
  • try [this](https://stackoverflow.com/questions/60270263/how-to-map-dart-string-with-ffi). The Dart FFI util handles that sizeof bit I think. – xerotolerant May 09 '22 at 11:39