Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NewFromBuffer/FindLoadBuffer error in NetVips.Native.osx-x64 #83

Closed
jsm174 opened this issue Jun 16, 2020 · 16 comments
Closed

NewFromBuffer/FindLoadBuffer error in NetVips.Native.osx-x64 #83

jsm174 opened this issue Jun 16, 2020 · 16 comments
Labels
enhancement New feature or request
Milestone

Comments

@jsm174
Copy link

jsm174 commented Jun 16, 2020

Now that NetVips.Native.osx-x64 8.9.2-build2 works in Mono, we were able to start running test cases on MacOS.

Out of our 113 tests, many of which use NetVips, only one has an error. The same test passes in Win x64.

The test uses Image.NewFromBuffer() and is passed in a byte[] containing a png.
I believe the error is ultimately with FindLoadBuffer.

Here is the stack trace:

    VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture [FAIL]
      System.DllNotFoundException : libvips-42.dll assembly:<unknown assembly> type:<unknown type> member:(null)
      Stack Trace:
          at (wrapper managed-to-native) NetVips.Internal.VipsForeign.FindLoadBuffer(byte&,ulong)
          at NetVips.Image.FindLoadBuffer (System.Byte[] data) [0x0000b] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Image.NewFromBuffer (System.Byte[] data, System.String strOptions, System.String access, System.Nullable`1[T] fail, NetVips.VOption kwargs) [0x00000] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at VisualPinball.Engine.VPT.Texture.GetImage () [0x0005f] in <59d605ba2c1e4e22be57eebc9092fe85>:0
          at VisualPinball.Engine.VPT.Texture.Analyze () [0x0001f] in <59d605ba2c1e4e22be57eebc9092fe85>:0
          at VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture () [0x00029] in <0b6668f7631a4c7ab37097cae33ebf25>:0
          at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
          at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <55adae4546cd485ba70e2948332ebe8c>:0

I looked at:

https://github.com/kleisauke/net-vips/blob/master/src/NetVips/Image.cs/#L305
https://github.com/kleisauke/net-vips/blob/master/src/NetVips/Image.cs/#L138

I checked the dylib for vips_foreign_find_load_buffer and it is there:

➜  Vendor git:(cross-platform-netvips) ✗ nm -gU libvips.42.dylib | grep find_load_buffer
0000000000154280 T _vips_foreign_find_load_buffer
@kleisauke kleisauke added the question Further information is requested label Jun 17, 2020
@kleisauke
Copy link
Owner

Based on the stack trace it looks like the Windows NetVips DLL (from the lib/net45 directory) is used on macOS. Mono is supposed to load the macOS DLL (from the runtimes/osx/lib/netstandard2.0 directory). The macOS DLL uses the *.dylib binaries, Windows uses the *.dll binaries and Linux uses the *.so.* binaries. These dynamic library names are used in the DllImport attribute and should therefore vary according to the OS it runs on.

I had a similar problem while testing this on Mono running on macOS. I noticed this during my initial attempt.

_CopyFilesMarkedCopyLocal:
  Copying file from "/Users/kleisauke/.nuget/packages/netvips/1.2.2/lib/net45/NetVips.dll" to "/Users/kleisauke/net-vips/tests/NetVips.Tests/bin/Release/net472/NetVips.dll".
  ...
  Copying file from "/Users/kleisauke/.nuget/packages/netvips.native.osx-x64/8.9.2-build2/runtimes/osx-x64/native/libgobject-2.0.dylib" to "/Users/kleisauke/net-vips/tests/NetVips.Tests/bin/Release/net472/libgobject-2.0.dylib".
  Copying file from "/Users/kleisauke/.nuget/packages/netvips.native.osx-x64/8.9.2-build2/runtimes/osx-x64/native/libvips.42.dylib" to "/Users/kleisauke/net-vips/tests/NetVips.Tests/bin/Release/net472/libvips.42.dylib".

So, it copies the Windows DLL instead than the macOS DLL to the output directory. Setting the RuntimeIdentifier to osx-x64 during restore/build seems to fix this:

_CopyFilesMarkedCopyLocal:
  Copying file from "/Users/kleisauke/.nuget/packages/netvips/1.2.2/runtimes/osx/lib/netstandard2.0/NetVips.dll" to "/Users/kleisauke/net-vips/tests/NetVips.Tests/bin/Release/net472/NetVips.dll".

msbuild $BUILD_PROJECT_FILE -t:build -restore /p:Configuration=Release ${RID:+/p:RuntimeIdentifier=$RID} /p:TestWithNuGetBinaries=false /nodeReuse:false

(I'm not sure why Mono didn't set this property by default, .NET Core doesn't have this kind of problems)

You could also use a DllMap to map the Windows library names (*.dll) to macOS library names (*.dylib). Create a new file called NetVips.dll.config in the same folder as the NetVips DLL with this content:

<?xml version="1.0" encoding="utf-8"?>
<!-- This configuration is only required for Mono runtime on platforms other than Windows -->
<configuration>
	<dllmap dll="libglib-2.0-0.dll" os="linux,freebsd,netbsd" target="libgobject-2.0.so.0"/>
	<dllmap dll="libgobject-2.0-0.dll" os="linux,freebsd,netbsd" target="libgobject-2.0.so.0"/>
	<dllmap dll="libvips-42.dll" os="linux,freebsd,netbsd" target="libvips.so.42"/>

	<dllmap dll="libglib-2.0-0.dll" os="osx" target="libgobject-2.0.dylib"/>
	<dllmap dll="libgobject-2.0-0.dll" os="osx" target="libgobject-2.0.dylib"/>
	<dllmap dll="libvips-42.dll" os="osx" target="libvips.42.dylib"/>
</configuration>

(untested)

@jsm174
Copy link
Author

jsm174 commented Jun 17, 2020

@kleisauke, thanks. I will give this a try.

I was thinking the System.DllNotFoundException was a red herring because all of our other test cases passed. They wouldn't have been able to if they weren't picking up the dylib versions??

@jsm174
Copy link
Author

jsm174 commented Jun 17, 2020

Two things I noticed:

  1. No glib, gobject, or vips dll files ended up in my .build/Release folder

  2. libglib-2.0.dylib wasn't in the .build/Release directory. It isn't in the osx nuget package either. I had it from something I must have installed with brew:

    libglib-2.0.dylib -> ../Cellar/glib/2.64.3/lib/libglib-2.0.dylib

    Anyway, I fixed that line in your dll map:

    <dllmap dll="libglib-2.0-0.dll" os="osx" target="libglib-2.0.dylib"/>

After that, now the test case errors like this:

mono .packages/xunit.runner.console.2.1.0/tools/xunit.console.exe VisualPinball.Engine.Test/.build/Release/VisualPinball.Engine.Test.dll
xUnit.net Console Runner (64-bit .NET 4.0.30319.42000)
  Discovering: VisualPinball.Engine.Test
  Discovered:  VisualPinball.Engine.Test
  Starting:    VisualPinball.Engine.Test

(process:10112): GLib-CRITICAL **: gpointer g_datalist_id_dup_data(GData **, GQuark, GDuplicateFunc, gpointer): assertion `key_id != 0' failed

(process:10112): GLib-CRITICAL **: gpointer g_datalist_id_dup_data(GData **, GQuark, GDuplicateFunc, gpointer): assertion `key_id != 0' failed
    VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture [FAIL]
      System.Exception : unsupported gtype for set , fundamental GBoxed, value type System.Byte[]
      Stack Trace:
          at NetVips.GValue.Set (System.Object value) [0x0046d] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.VipsObject.Set (System.IntPtr gtype, System.String name, System.Object value) [0x0000d] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Set (System.IntPtr gtype, NetVips.Enums+ArgumentFlags flags, System.String name, System.Object value) [0x00063] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Set (System.IntPtr gtype, NetVips.Enums+ArgumentFlags flags, NetVips.Image matchImage, System.String name, System.Object value) [0x0008c] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Call (System.String operationName, NetVips.VOption kwargs, NetVips.Image matchImage, System.Object[] args) [0x000cc] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Call (System.String operationName, NetVips.VOption kwargs, System.Object[] args) [0x00000] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Image.NewFromBuffer (System.Byte[] data, System.String strOptions, System.String access, System.Nullable`1[T] fail, NetVips.VOption kwargs) [0x0005b] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at VisualPinball.Engine.VPT.Texture.GetImage () [0x00036] in <b321a27a18f34b5389acb9624dd5fbe5>:0
          at VisualPinball.Engine.VPT.Texture.Analyze () [0x00017] in <b321a27a18f34b5389acb9624dd5fbe5>:0
          at VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture () [0x00015] in <9c6fb54ffd034e53824bd36d95ef4d39>:0
          at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
          at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <55adae4546cd485ba70e2948332ebe8c>:0
  Finished:    VisualPinball.Engine.Test
=== TEST EXECUTION SUMMARY ===
   VisualPinball.Engine.Test  Total: 113, Errors: 0, Failed: 1, Skipped: 0, Time: 10.332s

@kleisauke
Copy link
Owner

I was thinking the System.DllNotFoundException was a red herring because all of our other test cases passed. They wouldn't have been able to if they weren't picking up the dylib versions??

Ah, I read too fast. That's odd. I'm not sure why some of the tests work and others don't. Are they all using Image.NewFromBuffer? You could get more details about dll/dylib loading errors by setting these environment variables:

export MONO_LOG_LEVEL="debug"
export MONO_LOG_MASK="dll"

Also, maybe this HintPath should be adjusted if it runs on macOS?https://github.com/freezy/VisualPinball.Engine/blob/4e6a53ca19f40976dd9115ad9b045404b916ecaa/VisualPinball.Engine.Test/VisualPinball.Engine.Test.csproj#L193-L195

  1. No glib, gobject, or vips dll files ended up in my .build/Release folder

I think that's right. Only the native *.dylib binaries and NetVips.dll should be present on macOS.

  1. libglib-2.0.dylib wasn't in the .build/Release directory. It isn't in the osx nuget package either. I had it from something I must have installed with brew:
    libglib-2.0.dylib -> ../Cellar/glib/2.64.3/lib/libglib-2.0.dylib
    Anyway, I fixed that line in your dll map:
    <dllmap dll="libglib-2.0-0.dll" os="osx" target="libglib-2.0.dylib"/>

That is on purpose, libglib-2.0.dylib is not present because it is statically linked within libgobject-2.0.dylib. I wouldn't mix Homebrew's glib with the prebuilt binaries, they are incompatible.

@jsm174
Copy link
Author

jsm174 commented Jun 17, 2020

Ahh, I removed the NetVips.dll.config.

Here's what its saying:

Mono: DllImport error loading library 'libvips-42': 'dlopen(libvips-42, 9): image not found'.
Mono: DllImport error loading library 'libvips-42.dylib': 'dlopen(libvips-42.dylib, 9): image not found'.
Mono: DllImport error loading library 'libvips-42.dylib': 'dlopen(libvips-42.dylib, 9): image not found'.
Mono: DllImport error loading library 'libvips-42.so': 'dlopen(libvips-42.so, 9): image not found'.
Mono: DllImport error loading library 'libvips-42.bundle': 'dlopen(libvips-42.bundle, 9): image not found'.
Mono: DllImport error loading library 'libvips-42': 'dlopen(libvips-42, 9): image not found'.
Mono: DllImport unable to load library 'libvips-42.dll'.

The library name is libvips.42.dylib, not libvips-42.dylib

So I then cp libvips.42.dylib libvips-42.dylib:

Mono: DllImport error loading library 'libgobject-2.0-0': 'dlopen(libgobject-2.0-0, 9): image not found'.
Mono: DllImport error loading library 'libgobject-2.0-0.dylib': 'dlopen(libgobject-2.0-0.dylib, 9): image not found'.
Mono: DllImport error loading library 'libgobject-2.0-0.dylib': 'dlopen(libgobject-2.0-0.dylib, 9): image not found'.
Mono: DllImport error loading library 'libgobject-2.0-0.so': 'dlopen(libgobject-2.0-0.so, 9): image not found'.
Mono: DllImport error loading library 'libgobject-2.0-0.bundle': 'dlopen(libgobject-2.0-0.bundle, 9): image not found'.
Mono: DllImport error loading library 'libgobject-2.0-0': 'dlopen(libgobject-2.0-0, 9): image not found'.
Mono: DllImport unable to load library 'libgobject-2.0-0.dll'.
    VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture [FAIL]
      System.DllNotFoundException : libgobject-2.0-0.dll assembly:<unknown assembly> type:<unknown type> member:(null)
      Stack Trace:

Looks like that library name is libgobject-2.0.dylib

So I then cp libgobject-2.0.dylib libgobject-2.0-0.dylib:

Mono: DllImport error loading library 'libglib-2.0-0': 'dlopen(libglib-2.0-0, 9): image not found'.
Mono: DllImport error loading library 'libglib-2.0-0.dylib': 'dlopen(libglib-2.0-0.dylib, 9): image not found'.
Mono: DllImport error loading library 'libglib-2.0-0.dylib': 'dlopen(libglib-2.0-0.dylib, 9): image not found'.
Mono: DllImport error loading library 'libglib-2.0-0.so': 'dlopen(libglib-2.0-0.so, 9): image not found'.
Mono: DllImport error loading library 'libglib-2.0-0.bundle': 'dlopen(libglib-2.0-0.bundle, 9): image not found'.
Mono: DllImport error loading library 'libglib-2.0-0': 'dlopen(libglib-2.0-0, 9): image not found'.
Mono: DllImport unable to load library 'libglib-2.0-0.dll'.
Mono: DllImport searching in: 'libvips-42.dll' ('libvips-42.dylib').
Mono: Searching for 'vips_value_set_blob_free'.
Mono: Probing 'vips_value_set_blob_free'.
Mono: Found as 'vips_value_set_blob_free'.
Mono: DllImport searching in: 'libvips-42.dll' ('libvips-42.dylib').
Mono: Searching for 'vips_value_set_blob'.
Mono: Probing 'vips_value_set_blob'.
Mono: Found as 'vips_value_set_blob'.
Mono: DllImport searching in: 'libgobject-2.0-0.dll' ('libgobject-2.0-0.dylib').
Mono: Searching for 'g_value_unset'.
Mono: Probing 'g_value_unset'.
Mono: Found as 'g_value_unset'.
    VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture [FAIL]
      System.Exception : unsupported gtype for set , fundamental GBoxed, value type System.Byte[]
      Stack Trace:
          at NetVips.GValue.Set (System.Object value) [0x0046d] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.VipsObject.Set (System.IntPtr gtype, System.String name, System.Object value) [0x0000d] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Set (System.IntPtr gtype, NetVips.Enums+ArgumentFlags flags, System.String name, System.Object value) [0x00063] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Set (System.IntPtr gtype, NetVips.Enums+ArgumentFlags flags, NetVips.Image matchImage, System.String name, System.Object value) [0x0008c] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Call (System.String operationName, NetVips.VOption kwargs, NetVips.Image matchImage, System.Object[] args) [0x000cc] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Call (System.String operationName, NetVips.VOption kwargs, System.Object[] args) [0x00000] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Image.NewFromBuffer (System.Byte[] data, System.String strOptions, System.String access, System.Nullable`1[T] fail, NetVips.VOption kwargs) [0x0005b] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at VisualPinball.Engine.VPT.Texture.GetImage () [0x00036] in <b321a27a18f34b5389acb9624dd5fbe5>:0
          at VisualPinball.Engine.VPT.Texture.Analyze () [0x00017] in <b321a27a18f34b5389acb9624dd5fbe5>:0
          at VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture () [0x00015] in <9c6fb54ffd034e53824bd36d95ef4d39>:0
          at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
          at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <55adae4546cd485ba70e2948332ebe8c>:0
  Finished:    VisualPinball.Engine.Test

@kleisauke
Copy link
Owner

You still need the NetVips.dll.config if you want to deploy the lib/net45/NetVips.dll (which has Windows library names). The macOS NetVips.dll (i.e. runtimes/osx/lib/netstandard2.0/NetVips.dll) should not search for libglib-2.0-0, see:

internal const string GLib = "libgobject-2.0.dylib";

@jsm174
Copy link
Author

jsm174 commented Jun 17, 2020

Okay, I'll give that a try. It still looks like its trying to locate glib even if it is baked into libvips.

On a side note, I'm seeing why I didn't need a dll.config for my netminiz. I did it slightly different:

https://github.com/jsm174/net-miniz/blob/master/NetMiniZ/NetMinizUtils.cs#L45
https://github.com/jsm174/net-miniz/blob/master/NetMiniZ/Interop/OSXLibraries.cs#L8
https://github.com/jsm174/net-miniz/blob/master/NetMiniZ/Interop/WinLibraries.cs#L8

@jsm174
Copy link
Author

jsm174 commented Jun 17, 2020

Added the NetVips.dll.config back:

It looks like /Library/Frameworks/Mono.framework/Libraries/ has its own copies of libglib-2.0.dylib and libgobject-2.0.dylib, so it's picking it up there first.

Mono: DllImport loaded library '/Library/Frameworks/Mono.framework/Libraries/libglib-2.0.dylib'.
Mono: DllImport searching in: 'libglib-2.0.dylib' ('/Library/Frameworks/Mono.framework/Libraries/libglib-2.0.dylib').
Mono: Searching for 'g_malloc'.
Mono: Probing 'g_malloc'.
Mono: Found as 'g_malloc'.
Mono: DllImport searching in: 'libvips.42.dylib' ('libvips.42.dylib').
Mono: Searching for 'vips_value_set_blob_free'.
Mono: Probing 'vips_value_set_blob_free'.
Mono: Found as 'vips_value_set_blob_free'.
Mono: DllImport searching in: 'libvips.42.dylib' ('libvips.42.dylib').
Mono: Searching for 'vips_value_set_blob'.
Mono: Probing 'vips_value_set_blob'.
Mono: Found as 'vips_value_set_blob'.
Mono: DllImport searching in: 'libgobject-2.0.dylib' ('/Library/Frameworks/Mono.framework/Libraries/libgobject-2.0.dylib').
Mono: Searching for 'g_value_unset'.
Mono: Probing 'g_value_unset'.
Mono: Found as 'g_value_unset'.

(process:17604): GLib-CRITICAL **: gpointer g_datalist_id_dup_data(GData **, GQuark, GDuplicateFunc, gpointer): assertion `key_id != 0' failed
    VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture [FAIL]
      System.Exception : unsupported gtype for set , fundamental GBoxed, value type System.Byte[]
      Stack Trace:
          at NetVips.GValue.Set (System.Object value) [0x0046d] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.VipsObject.Set (System.IntPtr gtype, System.String name, System.Object value) [0x0000d] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Set (System.IntPtr gtype, NetVips.Enums+ArgumentFlags flags, System.String name, System.Object value) [0x00063] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Set (System.IntPtr gtype, NetVips.Enums+ArgumentFlags flags, NetVips.Image matchImage, System.String name, System.Object value) [0x0008c] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Call (System.String operationName, NetVips.VOption kwargs, NetVips.Image matchImage, System.Object[] args) [0x000cc] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Operation.Call (System.String operationName, NetVips.VOption kwargs, System.Object[] args) [0x00000] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at NetVips.Image.NewFromBuffer (System.Byte[] data, System.String strOptions, System.String access, System.Nullable`1[T] fail, NetVips.VOption kwargs) [0x0005b] in <a3ce067acea64a3abdc4d50d63adcbd3>:0
          at VisualPinball.Engine.VPT.Texture.GetImage () [0x00036] in <2a03a4554af74cb8a4a8c74dcd546e0b>:0
          at VisualPinball.Engine.VPT.Texture.Analyze () [0x00017] in <2a03a4554af74cb8a4a8c74dcd546e0b>:0
          at VisualPinball.Engine.Test.VPT.TextureBitmapTests.ShouldAnalyzeATransparentTexture () [0x00015] in <8e39aff847c34165b27edec11d12fffb>:0
          at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
          at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0006a] in <55adae4546cd485ba70e2948332ebe8c>:0

@jsm174
Copy link
Author

jsm174 commented Jun 17, 2020

That's what it was.

I temporarily swapped the symbolic link for libgobject so that
/Library/Frameworks/Mono.framework/Libraries/libgobject-2.0.dylib was pointing to .build\Release.

The test case then passed. Will have to figure out how to have it use yours instead of monos.

@jsm174
Copy link
Author

jsm174 commented Jun 18, 2020

So I'm still at a loss on this. Mono seems to need libgobject for other things, so I can't use both. The only way I can successfully get our code to run is to totally replace the symlink:

sudo rm /Library/Frameworks/Mono.framework/Libraries/libgobject-2.0.dylib
sudo ln -s /Users/jmillard/git/jsm174/VisualPinball.Engine/VisualPinball.Engine.Test/.build/Release/libgobject-2.0.dylib /Library/Frameworks/Mono.framework/Libraries/libgobject-2.0.dylib

@jsm174
Copy link
Author

jsm174 commented Jun 19, 2020

I worked on this some more..

Updated some other libs in the project, and added the dll map, and it seems to now be working!

Screen Shot 2020-06-18 at 10 20 01 PM

@kleisauke kleisauke added enhancement New feature or request and removed question Further information is requested labels Jun 21, 2020
kleisauke added a commit to kleisauke/libvips-packaging that referenced this issue Jun 21, 2020
Fixes compatibility with Mono and other libraries that depend on GLib.

See: kleisauke/net-vips#83.
@kleisauke kleisauke added this to the 1.2.3 milestone Jun 21, 2020
@kleisauke
Copy link
Owner

I was able to reproduce this. It looks like libgobject-2.0.dylib from Mono conflicts with the same binary provided by NetVips.Native. This can be fixed by setting the DYLD_LIBRARY_PATH environment variable to the output directory that contains the libgobject-2.0.dylib distributed by NetVips.Native (i.e. .build/Release/). I had a similar problem when testing with Homebrew's libvips, see:

# Prefer Homebrew's glib to avoid compatibility issues
# with the one provided by Mono.
export DYLD_LIBRARY_PATH=$(brew --prefix glib)/lib

Given that the above workaround is a hackish solution, I decided to build libvips as a single shared binary on Linux and macOS with GLib statically linked (commit kleisauke/libvips-packaging@8a89a8e) to avoid conflicts with other installed GLib libraries (if any).

This is released as NetVips.Native v8.9.2-build3 on NuGet which requires NetVips v1.2.3 (commit e04c6b0). If you deploy lib/net45/NetVips.dll, you'll need these changes in the NetVips.dll.config:

--- a/NetVips.dll.config
+++ b/NetVips.dll.config
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- This configuration is only required for Mono runtime on platforms other than Windows -->
 <configuration>
-	<dllmap dll="libglib-2.0-0.dll" os="linux,freebsd,netbsd" target="libgobject-2.0.so.0"/>
-	<dllmap dll="libgobject-2.0-0.dll" os="linux,freebsd,netbsd" target="libgobject-2.0.so.0"/>
+	<dllmap dll="libglib-2.0-0.dll" os="linux,freebsd,netbsd" target="libvips.so.42"/>
+	<dllmap dll="libgobject-2.0-0.dll" os="linux,freebsd,netbsd" target="libvips.so.42"/>
 	<dllmap dll="libvips-42.dll" os="linux,freebsd,netbsd" target="libvips.so.42"/>
 
-	<dllmap dll="libglib-2.0-0.dll" os="osx" target="libgobject-2.0.dylib"/>
-	<dllmap dll="libgobject-2.0-0.dll" os="osx" target="libgobject-2.0.dylib"/>
+	<dllmap dll="libglib-2.0-0.dll" os="osx" target="libvips.42.dylib"/>
+	<dllmap dll="libgobject-2.0-0.dll" os="osx" target="libvips.42.dylib"/>
 	<dllmap dll="libvips-42.dll" os="osx" target="libvips.42.dylib"/>
 </configuration>

Thanks for reporting this!

@jsm174
Copy link
Author

jsm174 commented Jun 22, 2020

@kleisauke - Thanks. I will give this a try in the morning..

I've had a very challenging go with DLLs / maps (and System.Runtime.CompilerServices.Unsafe.dll).

Since our project runs in Unity, I can not get it to accept individual specific maps. Ie, you have to change Unity's config:

/Applications/Unity/Hub/Editor/2019.4.1f1/Unity.app/Contents/MonoBleedingEdge/etc/mono/config

And out of the box Unity has the entries:

       <dllmap dll="libglib-2.0" target="libglib-2.0.so.0" os="!windows"/>
       <dllmap dll="libgobject-2.0" target="libgobject-2.0.so.0" os="!windows"/>

I wonder if these might collide with your updates.

It looks like this has existed for nearly a decade, so it's probably never going to change:

https://forum.unity.com/threads/what-is-the-correct-way-to-include-a-dll-config-file-for-multiple-platforms.320808/#post-2080776

https://forum.unity.com/threads/has-anyone-done-opencl-unity-on-mac.173728/#post-1207632

@kleisauke
Copy link
Owner

I don't like the DLLMap approach either, it's a bit unfortunate that Mono uses <RuntimeIdentifiers>win;win-x86;win-x64</RuntimeIdentifiers> by default on Linux and macOS. It ends up restoring Windows NuGet packages, which is wrong.

To fix this behavior of Mono, you could paste this in your csproj file:

  <!-- https://github.com/mono/mono/issues/15569 -->
  <PropertyGroup Condition="'$(MSBuildRuntimeType)' == 'Mono'">
    <RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux-x64</RuntimeIdentifier>
    <RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('OSX'))">osx-x64</RuntimeIdentifier>
    <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
  </PropertyGroup>

To ensure that it chooses the correct DLL after the restoring and building the project. This avoids having to use DLLMap at all.

@jsm174
Copy link
Author

jsm174 commented Jun 25, 2020

So I finally had a chance to test 1.2.3 and 8.9.2-build3, and it worked!

I still had no choice but to add the entries to Unity's config file. I'm a little concerned it could potentially clash with the default ones, but it does seem to be working well. (The names are different so I guess thats why it works).

Screen Shot 2020-06-25 at 9 11 45 AM

@kleisauke
Copy link
Owner

Great. I'm glad it's working now. I'll close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants