添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
3vti1qhhvcgxwespkody  ·  PyQt PySide2 ...·  2 月前    · 
聪明的椅子  ·  HtmlUnitDriver ...·  6 月前    · 
跑龙套的葫芦  ·  广州大剧院·  7 月前    · 
  1. Generate random number from C

Let’s create a c file named random_number.c For generating random number in c, we use rand . Here is the snippet

int fetch_number()
    int c, n;
    srand(time(0));
    n = rand() % 100 + 1;
    return n;

Note: We are capping the values from 0 to 100

We will create a header file randomnumber.h, and paste the declaration of our function inside it.

// randomnumber.h
int fetch_number();

Inside our random_number.c, we will import this header file and implement the definition of fetch_number . Our final file looks like this

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "randomnumber.h"
int main()
    return 0;
// Definition omitted for brevity. Basically, it's the above function only :)

Let’s test our c function, navigate to the folder containing the program and run

gcc random_number.c -o random_number

This generates our output file as random_number.o Run this output file by

./random_number

Output from C library
Output from C library

  • Next, we will create our dynamic library (librandomnumber.so)

To create a dynamic library, write the following command:

gcc -shared -o librandomnumber.so random_number.o
// librandomnumber.o is the name of your dynamic library
// random_number.o is the object file created from the above step

Note: The library name can be anything, but should start with “lib” and end with  .so

The compiler will later identify a library by searching for files beginning with “lib” and ending with the naming convention, .so

Dynamic Library in Linux
Dynamic Library in Linux

Call from Flutter on Linux

Drag and drop the library (librandomnumber.so) in our flutter project. We create a library subfolder and drop it there.

Libraries inside Flutter project
Libraries inside Flutter project

Steps to call a function from C
Steps to call a function from C

We will call our dynamic libraries from Flutter Desktop now using Dart FFI in Linux

  • Import the dart ffi package(present inside Flutter) as
import 'dart:ffi'

This has a class DynamicLibrary. We call the method open and load our dynamic library (librandomnumber.so).

final dyLib = DynamicLibrary.open(
'lib/library/linux/librandomnumber.so',
);

Lookup for the symbol from the loaded dynamic library using lookup or lookupFunction.

dyLib.lookup<NativeFunction<fetch_number_func>>(
   'fetch_number',
// This returns a pointer

Note: The lookup takes in a native function (which represents a function in C)

Our fetch_number_func is basically

typedef fetch_number_func = Int32 Function();

and this Int32 comes from dart:ffi, which represents a native signed 32 bit integer in C.

  • The pointer returned from the above step is converted into Dart function
final number = fetchNumberPointer.asFunction<FetchNumber>();
number(); // Call the function

where FetchNumber is our function

typedef FetchNumber = int Function();

Passing parameter from Dart to C

Let’s create a c file named string_ops.c We will define a function, which takes in a string parameter, reverses it, and sends it back. Here is the snippet

void reverse(char *str) {
  // Calculate length of string.
  int l = 0;
  while (*(str + l) != '\0')
// Initialize.
  int i;
  char *first, *last, temp;
  first = str;
  last = str;
  for (i = 0; i < l - 1; i++) {
    last++;
// Iterate from both ends, swapping first and last as we go.
  for (i = 0; i < l / 2; i++) {
    temp = *last;
    *last = *first;
    *first = temp;
first++;
    last--;

As seen in the above section, we will create a header file stringops.h and paste the declaration of our function inside it.

// stringops.h
void reverse(char *str);

Inside our string_ops.c, we will import this header file and implement the definition of reverse . Our final file looks like this

#include<stdio.h>
#include "stringops.h"
int main()
 return 0;
// Definition omitted for brevity. Basically, it's the above function only :)

Finally, we create our header file, libstringops.so (see the steps above)

Call from Flutter

We copy-paste this header file inside our flutter project

Libraries inside Flutter project
Libraries inside Flutter project

Open the dynamic library using the dart ffi

final dylib = DynamicLibrary.open(
   'lib/library/linux/libstringops.so',

Now we need to pass in the parameter, and this should be something that C understands. In short, we need to convert our Flutter Strings to Pointer.

Time to include package FFI

Our input (let's say a string) can be converted to UTF-8 pointer using toNativeUTF8,

String input = 'hello world';
final inputToUtf8 = input.toNativeUtf8();

Next, we need to look up the function

final reverse = dylib.lookupFunction<Void Function(Pointer<Utf8>),
        void Function(Pointer<Utf8>)>('reverse');

Note: First param is the C function signature, and second param is the Dart function signature.

Now, we have a function that takes in a parameter of Pointer<Utf8> and we pass in our inputToUtf8 

reverse(inputToUtf8);
final resp = inputToUtf8.toDartString();

Finally, the response(which is of type UTF-8) is converted toDartString

  • One last thing, toNativeUtf8 uses an allocator to allocate C memory. Remember, in C we need to explicitly free the memory used.
  • This is done by calling free 
  • malloc.free(inputToUtf8);

    Passing structs from Dart to C

    In the header file stringops.h, let’s add in our struct

    struct Name
        char *firstname;
        char *lastname;
    struct Name create_name(char *firstname, char *lastname);

    Inside our string_ops.c, we have already imported this header file. Let’s implement the definition of create_name . Our final file looks like this

    #include<stdio.h>
    #include "stringops.h"
    int main()
     return 0;
    struct Name create_name(char *firstname, char *lastname) {
     struct Name name;
     name.firstname = firstname;
     name.lastname = lastname;
     return name; 
    

    Finally, we create our header file, libstringops.so (see the steps above)

    Call from Flutter

    Note: We require Dart 2.12 and onwards to call structs from ffi

    We copy-paste this header file inside our flutter project

    Libraries inside Flutter project
    Libraries inside Flutter project

    We already have our dynamic library opened (see the above section), now we need to look up our create_name function.

    final createName =
      dylib.lookupFunction<CreateNameNative, CreateName>('create_name');

    As we know now, the lookup function takes in a C function and a Dart function. Our functions look like

    // For structs
    typedef CreateNameNative = Name Function(
        Pointer<Utf8> firstName, Pointer<Utf8> lastName);
    typedef CreateName = Name Function(
        Pointer<Utf8> firstName, Pointer<Utf8> lastName);

    since, we need to pass in the two parameters

    Now, here is something new, we have Name 

    class Name extends Struct {
      external Pointer<Utf8> firstName;
      external Pointer<Utf8> lastName;
    
  • Dart introduces Struct, the supertype of all FFI struct types.
  • FFI struct types should extend this class and declare fields corresponding to the underlying native structure.
  • All field declarations in a Struct subclass declaration must be marked external

    Rest is the same, we pass in our inputs as toNativeUtf8

    String first = 'Aseem';
    String second = 'Wangoo';
    final fNameUtf8 = first.toNativeUtf8();
    final lNameUtf8 = second.toNativeUtf8();
    final name = createName(fNameUtf8, lNameUtf8);
    // createName is from the above

    Finally, we have our response in the variable name The response(which is of type UTF-8) is converted toDartString

    final fname = name.firstName.toDartString();
    final lname = name.lastName.toDartString();

    The memory is freed using free

    malloc.free(fNameUtf8);
    malloc.free(lNameUtf8);

    Built on Forem — the open source software that powers DEV and other inclusive communities.

    Made with love and Ruby on Rails. DEV Community © 2016 - 2024.

  •