Skip to content

Fix macos framework bindings#1409

Open
Lxixnxuxs wants to merge 3 commits intoanalogdevicesinc:mainfrom
Lxixnxuxs:fix-macos-framework-bindings
Open

Fix macos framework bindings#1409
Lxixnxuxs wants to merge 3 commits intoanalogdevicesinc:mainfrom
Lxixnxuxs:fix-macos-framework-bindings

Conversation

@Lxixnxuxs
Copy link

@Lxixnxuxs Lxixnxuxs commented Mar 15, 2026

PR Description

Fixes #1408

On macOS, libiio installs as a framework by default (OSX_FRAMEWORK=ON). Both the Python and C# bindings fail to load the library in this case:

Python (bindings/python/iio/__init__.py):

  • find_library("iio") returns a framework path like /Library/Frameworks/iio.framework/Versions/1.0/iio where the basename is just iio. The code unconditionally splits on .so. to extract the version, causing an IndexError.
  • Additionally, _path.islink() was called before the None check on the library path.
  • Fix: check for .so. first, fall back to extracting the version from the /Versions/ component of the framework path, and move the None guard up.

C# (bindings/csharp/IioLib.cs):

  • DllImport("libiio1.dll") fails because .NET's native loader does not search /Library/Frameworks/ on macOS, resulting in a DllNotFoundException.
  • Fix: add a NativeLibrary.SetDllImportResolver in a static constructor that resolves to the framework path on macOS. This is the standard .NET mechanism for custom native library resolution (available since .NET Core 3.0).

Both fixes are no-ops on Linux and Windows. I did not add any in-code documentation because of isolated nature of the bug.

PR Type

  • Bug fix (a change that fixes an issue)
  • New feature (a change that adds new functionality)
  • Breaking change (a change that affects other repos or cause CIs to fail)

PR Checklist

  • I have conducted a self-review of my own code changes
  • I have commented new code, particularly complex or unclear areas
  • I have checked that I did not introduce new warnings or errors (CI output)
  • I have checked that components that use libiio did not get broken
  • I have updated the documentation accordingly (GitHub Pages, READMEs, etc)

Signed-off-by: Linus Meierhoefer <linusmeierhoefer@protonmail.com>
…dings

Signed-off-by: Linus Meierhoefer <linusmeierhoefer@protonmail.com>
@RubenNatanael
Copy link
Collaborator

Hi @Lxixnxuxs, the pipeline is failing during the Windows build. After inspection, it seems the CI environment is using C# 5, but the out IntPtr handle inline declaration syntax requires at least C# 7.0.
To resolve this, I recommend either updating the CMakeLists.txt from /langversion:5 to /langversion:7 (@dNechita , do we want to move to a newer version?) or refactoring the code to be backward compatible.

@Lxixnxuxs
Copy link
Author

Hi @RubenNatanael, thanks for flagging this. I just looked into the Windows CI and realized that the issue is deeper, i.e. that the project is linked against .NET Framework/mono, which does not expose the NativeLibrary API i used to resolve the macos C# bindings against (I assumed .NET core). Instead i can go ahead, revert the change and just add a top entry for osx to DllMap, which should work with mono. What are your thoughts?

@RubenNatanael
Copy link
Collaborator

I think the best approach is to make it compatible with the current version until is decided to move to a newer version, but let's wait for a answer from @dNechita

@dNechita
Copy link
Contributor

Let's keep the C# 5 for now.

Replace NativeLibrary.SetDllImportResolver (requires .NET Core / C# 7+)
with a platform-specific DllMap entry in libiio-sharp.dll.config, which is
compatible with the project's Mono / C# 5 target.

Signed-off-by: Linus Meierhoefer <linusmeierhoefer@protonmail.com>
@Lxixnxuxs
Copy link
Author

Hi @RubenNatanael, @dNechita, thanks for the feedback. I've replaced the SetDllImportResolver approach with a DllMap entry, which is compatible with Mono / C# 5. The CI now passes.

However, DllMap is a Mono-only mechanism, so users running the bindings on .NET Core on macOS (as myself) would still need to handle native library resolution manually. But I guess this is fine considering this repo targeting C# 5.

@RubenNatanael
Copy link
Collaborator

@Lxixnxuxs, Do you think this issue could be resolved using preprocessor symbols instead? For example, we could use #if NET7_0_OR_GREATER or NETCOREAPP to run your original code, and fall back to the compatible approach otherwise (e.g., the DllMap solution),

@Lxixnxuxs
Copy link
Author

Hi @RubenNatanael, I looked into this but unfortunately directly using preprocessor symbols like NET7_0_OR_GREATER or NETCOREAPP won't work with the current build setup. Those symbols are defined by MSBuild(.NET SDK) when building SDK-style projects, not by the compiler itself. Since in this project, the C# bindings are compiled via direct mcs/csc invocation through CMake, none of those symbols are available.

We could work around that by passing a custom /define: flag from CMake (e.g. /define:OSX on macOS), but the problem is that mcs compiles against Mono's class libraries, which don't include the classSystem.Runtime.InteropServices.NativeLibrary, that my original code was relying on. So even with the correct preprocessor guard, the code inside the #if block would fail to compile, as the type doesn't exist in mono.

Supporting both paths (NativeLibrary for .NET Core, DllMap for Mono) would require maintaining two separate build toolchains in CMake. We could do that, however that stretches the scope of this PR a bit.

@RubenNatanael
Copy link
Collaborator

Thanks @Lxixnxuxs, I was asking because we already have used a similar approach in UTF8Marshaler.cs file (https://github.com/analogdevicesinc/libiio/blob/main/bindings/csharp/UTF8Marshaler.cs#L31)

@Lxixnxuxs
Copy link
Author

Lxixnxuxs commented Mar 17, 2026

@RubenNatanael Ok i see, in that case (i.e. parts of the C# code assuming there is a .NET core build system), would it also make sense to add a proper .csproj? And maybe also choosing it, if available, as a default in the cmake build?
Otherwise it is quite hard for an outsider to determine that this project can actually be used with .NET core and that the compilation differs depending on the build.

@RubenNatanael
Copy link
Collaborator

Hi @Lxixnxuxs, thank you for your analysis and explanation; it's good to know all this. Currently, we don't have a request to move to .NET Core or a higher C# version. Creating and maintaining two different builds would require a significant amount of work, so we will leave it as it is for now. Thanks again!

@Lxixnxuxs
Copy link
Author

Hi @RubenNatanael, alright makes sense. So should I change anything else concerning this PR?

@RubenNatanael
Copy link
Collaborator

Hi @RubenNatanael, alright makes sense. So should I change anything else concerning this PR?

Everything looks good from my side. Just waiting for a final approval from a reviewer before we move forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python and C# bindings fail to load libiio on macOS when installed with default build settings

3 participants