I am trying to use libpng1.6
to load a png from file, but the execution fails with a segmentation fault.
I load the library and libpng
function called png_image_begin_read_from_file
as shown:
final dylib = ffi.DynamicLibrary.open(
"/opt/homebrew/Cellar/libpng/1.6.37/lib/libpng.dylib");
final dart_function_t png_image_begin_read_from_file = dylib
.lookup<ffi.NativeFunction<native_function_t>>(
'png_image_begin_read_from_file')
.asFunction();
Here is the full snippet to reproduce the problem.
import 'dart:ffi' as ffi;
import 'package:ffi/ffi.dart';
class png_controlp extends ffi.Opaque {}
// Fields taken from "png.h"
class PngImage extends ffi.Struct {
@ffi.Uint32()
external int version,
width,
height,
flags,
format,
colormap_entries,
warning_or_error;
@ffi.Array(64)
external ffi.Array<ffi.Char> message;
external ffi.Pointer<png_controlp> opaque;
}
// native type
typedef native_function_t = ffi.Int32 Function(
ffi.Pointer<PngImage> image, ffi.Pointer<Utf8> file_name);
// dart type
typedef dart_function_t = int Function(
ffi.Pointer<PngImage> image, ffi.Pointer<Utf8> file_name);
void main() {
final dylib = ffi.DynamicLibrary.open(
"/opt/homebrew/Cellar/libpng/1.6.37/lib/libpng.dylib");
final dart_function_t png_image_begin_read_from_file = dylib
.lookup<ffi.NativeFunction<native_function_t>>(
'png_image_begin_read_from_file')
.asFunction();
final path = "my_image.png";
ffi.Pointer<PngImage> p_pngImage = calloc<PngImage>();
p_pngImage.ref.version = 1;
final res = png_image_begin_read_from_file(p_pngImage, path.toNativeUtf8());
}
===== CRASH =====
si_signo=Segmentation fault: 11(11), si_code=2, si_addr=0x11
version=2.17.0-266.7.beta (beta) (Mon Apr 25 14:54:53 2022 +0000) on "macos_arm64"
pid=42862, thread=20995, isolate_group=main(0x123810200), isolate=main(0x122034200)
isolate_instructions=10263d8c0, vm_instructions=10263d8c0
pc 0x00000001051b6604 fp 0x000000016e1be830 png_image_free+0x24
pc 0x00000001051b66c8 fp 0x000000016e1be850 png_image_error+0x38
It looks like the Dart struct is in the wrong order - check the C header:
So, the Dart struct should be:
Also note the comment in the header:
Be sure to set the
opaque
pointer tonullPtr
- though this is probably unnecessary as you are usingcalloc
to create it - which will zero it for you. (Also remember that you may need to make another C call to free stuff allocated by theread_from_file
method, and alsofree
anything that youcalloc
.)