Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

278
Visualizações
Dart FFI keep Struct pointer

I am trying to call a C library from dart. The C code as a genertor method such as

a_struc  create_struct(void);

and then methods that take in a pointer to struct, such as:

const char *
 get_info(const a_struc * s);

I have created the dart binding using ffigen and I have

class a_struct extends ffi.Struct {
}

a_struct create_struct() {
    return create_struct();
  }

late final create_structPtr =
   _lookup<ffi.NativeFunction<a_struct Function()>>(
       'create_struct');
late final create_struct =
   create_structPtr
       .asFunction<a_struct Function()>();

and

ffi.Pointer<ffi.Int8> get_info(
    ffi.Pointer<a_struct> a_struct,
  ) {
    return get_info(
      a_struct,
    );
  }

late final get_infoPtr = _lookup<
    ffi.NativeFunction<
        ffi.Pointer<ffi.Int8> Function(
            ffi.Pointer<a_struct>)>>('rcl_publisher_get_topic_name');
late final get_info =
    get_infoPtr.asFunction<
        ffi.Pointer<ffi.Int8> Function(ffi.Pointer<a_struct>)>();

My problem is that I don't know how to call the method get_info from the dart a_struct generated by create_struct. Indeed, get_info expects a ffi.Pointer<a_struct> but I only generate a a_struct without the pointer. Since dart deprecated .addressOf, how can I obtain a ffi.Pointer<a_struct> from create_struct?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

When you return a struct by value from C to Dart, the struct is copied into a relocatable memory block that's fully managed by Dart.

Dart doesn't provide an API that exposes the underlying address of these objects, and so if you need to pass that data to C by reference, you'll need to store it in a non-relocatable native memory region (i.e. heap allocate it or use global C state) and keep track of a pointer to it on the Dart side.

If you can't (or would prefer not to) modify the C++ library, you could use the Dart FFI package to call malloc<MyStruct>() and then copy the struct into the newly allocated space with ref= setter.

final ffi.Pointer<MyStruct> myStructPtr = malloc<MyStruct>()
  ..ref = createStructFn();

// ... pass myStructPtr to other FFI functions by reference ...

malloc.free(myStructPtr);

Note that the ref= setter in StructPointer landed in Dart on Jan 12, 2022 (quite recently, at the time of writing).

Full example below.

C++:

// Build command: g++ -shared lib.cc -o lib.dll -Wl,--out-implib,lib.a

#include <cstdlib>

extern "C" {
  typedef struct {
    const char* info;
  } MyStruct;

  MyStruct CreateStruct() {
    return {.info = "Hello Dart!"};
  }

  const char* GetInfo(MyStruct* s) {
    return s->info;
  }
}

Dart:

import 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart';

class MyStruct extends ffi.Struct {
  external ffi.Pointer<Utf8> info;
}

typedef CreateStruct = MyStruct Function();
typedef GetInfo = ffi.Pointer<Utf8> Function(ffi.Pointer<MyStruct>);

void main() {
  // Load FFI procs.
  final lib = ffi.DynamicLibrary.open('lib.dll');
  final createStructFn =
      lib.lookupFunction<CreateStruct, CreateStruct>('CreateStruct');
  final getInfoFn = lib.lookupFunction<GetInfo, GetInfo>('GetInfo');

  // Allocate a native memory region and copy the returned struct into it.
  final myStructPtr = malloc<MyStruct>()..ref = createStructFn();

  // It's a pointer, so we can pass by reference.
  final result = getInfoFn(myStructPtr);
  print(result.toDartString());

  // Cleanup!
  malloc.free(myStructPtr);
}

As an aside: Before the "returning structs by value" features landed, all structs passed from C to Dart had to be passed by reference. That's the reason addressOf was initially available on all FFI structs -- they all were ffi.Pointers. To support Dart-managed storage backends, ffi.Pointer needed to be decoupled from ffi.Struct. The result is a much more sensible API! For example, you can have a Pointer<Pointer<Uint8>> and it functions exactly as you'd expect.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda