Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ bin/
obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
/_ReSharper.Caches/
.vscode/
2 changes: 0 additions & 2 deletions NativeFileDialogSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeFileDialogSharp", "Na
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeFileDialogSharpSandbox", "NativeFileDialogSharpSandbox\NativeFileDialogSharpSandbox.csproj", "{427E5F76-8418-4EA3-9AA3-C1DBFDE0478F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeFileDialogSharpSandboxNetFramework", "NativeFileDialogSharpSandboxNetFramework\NativeFileDialogSharpSandboxNetFramework.csproj", "{0FD91168-D8F5-4776-8D91-CB9B9C55AA1B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
116 changes: 69 additions & 47 deletions NativeFileDialogSharp/Native/NativeFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,88 +10,110 @@ public struct nfdpathset_t
public UIntPtr count;
}

public enum nfdresult_t
public enum Nfdresult_t
{
NFD_ERROR,
NFD_OKAY,
NFD_CANCEL
}

public static class NativeFunctions
public static partial class NativeFunctions
{
public const string LibraryName = "nfd";

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_OpenDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_OpenDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_OpenDialogMultiple(byte* filterList, byte* defaultPath,
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_OpenDialogMultiple(byte* filterList, byte* defaultPath,
nfdpathset_t* outPaths);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_SaveDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_SaveDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_PickFolder(byte* defaultPath, out IntPtr outPath);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_PickFolder(byte* defaultPath, out IntPtr outPath);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe byte* NFD_GetError();
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial byte* NFD_GetError();

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe UIntPtr NFD_PathSet_GetCount(nfdpathset_t* pathSet);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial UIntPtr NFDPathSetGetCount(nfdpathset_t* pathSet);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe byte* NFD_PathSet_GetPath(nfdpathset_t* pathSet, UIntPtr index);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial byte* NFDPathSetGetPath(nfdpathset_t* pathSet, UIntPtr index);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void NFD_PathSet_Free(nfdpathset_t* pathSet);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial void NFDPathSetFree(nfdpathset_t* pathSet);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void NFD_Dummy();
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial void NFD_Dummy();

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe IntPtr NFD_Malloc(UIntPtr bytes);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial IntPtr NFD_Malloc(UIntPtr bytes);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void NFD_Free(IntPtr ptr);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial void NFD_Free(IntPtr ptr);
}

public static class NativeFunctions32
public static partial class NativeFunctions32
{
public const string LibraryName = "nfd_x86";

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_OpenDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_OpenDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_OpenDialogMultiple(byte* filterList, byte* defaultPath,
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_OpenDialogMultiple(byte* filterList, byte* defaultPath,
nfdpathset_t* outPaths);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_SaveDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_SaveDialog(byte* filterList, byte* defaultPath, out IntPtr outPath);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe nfdresult_t NFD_PickFolder(byte* defaultPath, out IntPtr outPath);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial Nfdresult_t NFD_PickFolder(byte* defaultPath, out IntPtr outPath);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe byte* NFD_GetError();
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial byte* NFD_GetError();

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe UIntPtr NFD_PathSet_GetCount(nfdpathset_t* pathSet);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial UIntPtr NFD_PathSet_GetCount(nfdpathset_t* pathSet);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe byte* NFD_PathSet_GetPath(nfdpathset_t* pathSet, UIntPtr index);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial byte* NFD_PathSet_GetPath(nfdpathset_t* pathSet, UIntPtr index);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void NFD_PathSet_Free(nfdpathset_t* pathSet);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial void NFD_PathSet_Free(nfdpathset_t* pathSet);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void NFD_Dummy();
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial void NFD_Dummy();

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe IntPtr NFD_Malloc(UIntPtr bytes);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial IntPtr NFD_Malloc(UIntPtr bytes);

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
public static extern unsafe void NFD_Free(IntPtr ptr);
[LibraryImport(LibraryName)]
[UnmanagedCallConv(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
public static unsafe partial void NFD_Free(IntPtr ptr);
}
}
4 changes: 2 additions & 2 deletions NativeFileDialogSharp/NativeFileDialogSharp.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<LangVersion>7.3</LangVersion>
<PackageVersion>0.5.0</PackageVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageLicenseExpression>Zlib</PackageLicenseExpression>
<Authors>milleniumbug</Authors>
<PackageProjectUrl>https://github.com/milleniumbug/NativeFileDialogSharp</PackageProjectUrl>
<RepositoryUrl>https://github.com/milleniumbug/NativeFileDialogSharp</RepositoryUrl>
<Description>Cross-platform native file dialog controls for Windows, Linux and macOS</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
Expand Down
41 changes: 20 additions & 21 deletions NativeFileDialogSharp/NativeWrappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@ private static bool Is32BitWindowsOnNetFramework()
try
{
// we call a function that does nothing just to test if we can load it properly
NativeFileDialogSharp.Native.NativeFunctions.NFD_Dummy();
NativeFunctions.NFD_Dummy();
return false;
}
catch
{
// a call to a default library failed, let's attempt the other one
try
{
NativeFileDialogSharp.Native.NativeFunctions32.NFD_Dummy();
NativeFunctions32.NFD_Dummy();
return true;
}
catch
Expand Down Expand Up @@ -77,15 +77,14 @@ public static unsafe DialogResult FileOpen(string filterList = null, string defa
{
string path = null;
string errorMessage = null;
IntPtr outPathIntPtr;
var result = need32bit
? NativeFunctions32.NFD_OpenDialog(filterListNts, defaultPathNts, out outPathIntPtr)
var result = need32bit
? NativeFunctions32.NFD_OpenDialog(filterListNts, defaultPathNts, out nint outPathIntPtr)
: NativeFunctions.NFD_OpenDialog(filterListNts, defaultPathNts, out outPathIntPtr);
if (result == nfdresult_t.NFD_ERROR)
if (result == Nfdresult_t.NFD_ERROR)
{
errorMessage = FromUtf8(NativeFunctions.NFD_GetError());
}
else if (result == nfdresult_t.NFD_OKAY)
else if (result == Nfdresult_t.NFD_OKAY)
{
var outPathNts = (byte*)outPathIntPtr.ToPointer();
path = FromUtf8(outPathNts);
Expand All @@ -107,11 +106,11 @@ public static unsafe DialogResult FileSave(string filterList = null, string defa
var result = need32bit
? NativeFunctions32.NFD_SaveDialog(filterListNts, defaultPathNts, out outPathIntPtr)
: NativeFunctions.NFD_SaveDialog(filterListNts, defaultPathNts, out outPathIntPtr);
if (result == nfdresult_t.NFD_ERROR)
if (result == Nfdresult_t.NFD_ERROR)
{
errorMessage = FromUtf8(NativeFunctions.NFD_GetError());
}
else if (result == nfdresult_t.NFD_OKAY)
else if (result == Nfdresult_t.NFD_OKAY)
{
var outPathNts = (byte*)outPathIntPtr.ToPointer();
path = FromUtf8(outPathNts);
Expand All @@ -132,11 +131,11 @@ public static unsafe DialogResult FolderPicker(string defaultPath = null)
var result = need32bit
? NativeFunctions32.NFD_PickFolder(defaultPathNts, out outPathIntPtr)
: NativeFunctions.NFD_PickFolder(defaultPathNts, out outPathIntPtr);
if (result == nfdresult_t.NFD_ERROR)
if (result == Nfdresult_t.NFD_ERROR)
{
errorMessage = FromUtf8(NativeFunctions.NFD_GetError());
}
else if (result == nfdresult_t.NFD_OKAY)
else if (result == Nfdresult_t.NFD_OKAY)
{
var outPathNts = (byte*)outPathIntPtr.ToPointer();
path = FromUtf8(outPathNts);
Expand All @@ -158,20 +157,20 @@ public static unsafe DialogResult FileOpenMultiple(string filterList = null, str
var result = need32bit
? NativeFunctions32.NFD_OpenDialogMultiple(filterListNts, defaultPathNts, &pathSet)
: NativeFunctions.NFD_OpenDialogMultiple(filterListNts, defaultPathNts, &pathSet);
if (result == nfdresult_t.NFD_ERROR)
if (result == Nfdresult_t.NFD_ERROR)
{
errorMessage = FromUtf8(NativeFunctions.NFD_GetError());
}
else if (result == nfdresult_t.NFD_OKAY)
else if (result == Nfdresult_t.NFD_OKAY)
{
var pathCount = (int)NativeFunctions.NFD_PathSet_GetCount(&pathSet).ToUInt32();
var pathCount = (int)NativeFunctions.NFDPathSetGetCount(&pathSet).ToUInt32();
paths = new List<string>(pathCount);
for (int i = 0; i < pathCount; i++)
{
paths.Add(FromUtf8(NativeFunctions.NFD_PathSet_GetPath(&pathSet, new UIntPtr((uint)i))));
paths.Add(FromUtf8(NativeFunctions.NFDPathSetGetPath(&pathSet, new UIntPtr((uint)i))));
}

NativeFunctions.NFD_PathSet_Free(&pathSet);
NativeFunctions.NFDPathSetFree(&pathSet);
}

return new DialogResult(result, null, paths, errorMessage);
Expand All @@ -181,21 +180,21 @@ public static unsafe DialogResult FileOpenMultiple(string filterList = null, str

public class DialogResult
{
private readonly nfdresult_t result;
private readonly Nfdresult_t result;

public string Path { get; }

public IReadOnlyList<string> Paths { get; }

public bool IsError => result == nfdresult_t.NFD_ERROR;
public bool IsError => result == Nfdresult_t.NFD_ERROR;

public string ErrorMessage { get; }

public bool IsCancelled => result == nfdresult_t.NFD_CANCEL;
public bool IsCancelled => result == Nfdresult_t.NFD_CANCEL;

public bool IsOk => result == nfdresult_t.NFD_OKAY;
public bool IsOk => result == Nfdresult_t.NFD_OKAY;

internal DialogResult(nfdresult_t result, string path, IReadOnlyList<string> paths, string errorMessage)
internal DialogResult(Nfdresult_t result, string path, IReadOnlyList<string> paths, string errorMessage)
{
this.result = result;
Path = path;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Loading