Skip to content

Commit 9bad6a5

Browse files
committed
use source generator to define all the interop functions
1 parent c2d5748 commit 9bad6a5

File tree

13 files changed

+4661
-644
lines changed

13 files changed

+4661
-644
lines changed

Secp256k1.Net.SourceGenerator/InteropGenerator.cs

Lines changed: 593 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<IsRoslynComponent>true</IsRoslynComponent>
6+
<LangVersion>latest</LangVersion>
7+
<Nullable>enable</Nullable>
8+
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
13+
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all">
14+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
15+
</PackageReference>
16+
<PackageReference Include="System.Text.Json" Version="8.0.5" PrivateAssets="all" GeneratePathProperty="true" />
17+
</ItemGroup>
18+
19+
</Project>

Secp256k1.Net.Test/Tests.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ public void NativeLibResolveLoadClose()
388388
try
389389
{
390390
File.Copy(origLibPath, tempLibPath, overwrite: true);
391-
var libPtr = LoadLibNative.LoadLib(tempLibPath);
391+
var libPtr = LoadLibNative.LoadLibrary(tempLibPath, out var _);
392392
LoadLibNative.CloseLibrary(libPtr);
393393
}
394394
finally
@@ -435,7 +435,7 @@ public void NativeLibResolveWithExtraSearchPaths()
435435
Assert.AreEqual(tempLibPath, resolvedPath, "Library should be resolved from ExtraNativeLibSearchPaths");
436436

437437
// Actually load the library to prove it works
438-
var libPtr = LoadLibNative.LoadLib(resolvedPath);
438+
var libPtr = LoadLibNative.LoadLibrary(resolvedPath, out var _);
439439
Assert.AreNotEqual(IntPtr.Zero, libPtr, "Library should load successfully");
440440
LoadLibNative.CloseLibrary(libPtr);
441441
}
@@ -454,9 +454,8 @@ public void NativeLibLoadFailure()
454454
{
455455
var exception = Assert.ThrowsException<Exception>(() =>
456456
{
457-
LoadLibNative.LoadLib("invalid_lib_test_123456");
457+
LoadLibNative.LoadLibrary("invalid_lib_test_123456", out var _);
458458
});
459-
StringAssert.Contains(exception.Message, "loading failed");
460459
}
461460

462461
[TestMethod]
@@ -467,19 +466,22 @@ public void NativeLibCloseFailure()
467466
{
468467
LoadLibNative.CloseLibrary(new IntPtr(int.MaxValue));
469468
});
470-
StringAssert.Contains(exception.Message, "closing failed");
471469
}
472470

473471
[TestMethod]
474472
public void NativeLibSymbolLoadFailure()
475473
{
476474
var libPath = LibPathResolver.Resolve(Secp256k1.LIB);
477-
var libPtr = LoadLibNative.LoadLib(libPath);
478-
var exception = Assert.ThrowsException<Exception>(() =>
475+
var libPtr = LoadLibNative.LoadLibrary(libPath, out var _);
476+
try
479477
{
480-
LoadLibNative.GetDelegate<Action>(libPtr, "invalid_symbol_name_test_123456");
481-
});
482-
StringAssert.Contains(exception.Message, "symbol failed");
478+
LoadLibNative.GetSymbolPointer(libPtr, "invalid_symbol_name_test_123456");
479+
Assert.Fail("Expected an exception");
480+
}
481+
catch (Exception ex) when (ex is not AssertFailedException)
482+
{
483+
// success - any exception was thrown
484+
}
483485
}
484486

485487
[TestMethod]

Secp256k1.Net/DynamicLinking/DynamicLinkingMacOS.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ namespace Secp256k1Net.DynamicLinking
55
{
66
static class DynamicLinkingMacOS
77
{
8+
public const int RTLD_NOW = 2;
9+
810
const string LIBDL = "libdl";
911

1012
[DllImport(LIBDL)]

Secp256k1.Net/Generated/secp256k1-api.json

Lines changed: 3039 additions & 0 deletions
Large diffs are not rendered by default.

Secp256k1.Net/Interop.cs

Lines changed: 0 additions & 375 deletions
This file was deleted.

Secp256k1.Net/LoadLibNative.cs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,61 @@ namespace Secp256k1Net
99
{
1010
internal static class LoadLibNative
1111
{
12+
13+
#if NET8_0_OR_GREATER
14+
/// <summary>
15+
/// Loads the native library using modern .NET NativeLibrary APIs.
16+
/// Tries standard resolution first, then falls back to LibPathResolver.
17+
/// </summary>
18+
/// <param name="libName">The library name (e.g., "secp256k1").</param>
19+
/// <param name="libPath">Output parameter that receives the resolved library path.</param>
20+
/// <returns>The handle to the loaded library.</returns>
21+
public static IntPtr LoadLibrary(string libName, out string libPath)
22+
{
23+
var assembly = typeof(Secp256k1).Assembly;
24+
// Try standard resolution first (works for RID-specific builds and NativeAOT)
25+
if (NativeLibrary.TryLoad(libName, assembly,
26+
DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.ApplicationDirectory,
27+
out var handle))
28+
{
29+
libPath = libName;
30+
return handle;
31+
}
32+
33+
// Also try with lib prefix for Unix
34+
var libPrefixedName = "lib" + libName;
35+
if (NativeLibrary.TryLoad(libPrefixedName, assembly,
36+
DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.ApplicationDirectory,
37+
out handle))
38+
{
39+
libPath = libPrefixedName;
40+
return handle;
41+
}
42+
43+
// Fallback: use LibPathResolver for comprehensive path probing
44+
libPath = LibPathResolver.Resolve(libName);
45+
return NativeLibrary.Load(libPath);
46+
}
47+
48+
public static void CloseLibrary(IntPtr lib)
49+
{
50+
NativeLibrary.Free(lib);
51+
}
52+
53+
public static IntPtr GetSymbolPointer(IntPtr libPtr, string symbolName)
54+
{
55+
return NativeLibrary.GetExport(libPtr, symbolName);
56+
}
57+
58+
#else
59+
1260
static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
1361
static readonly bool IsMacOS = RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
1462
static readonly bool IsLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
1563

16-
public static IntPtr LoadLib(string libPath)
64+
public static IntPtr LoadLibrary(string libName, out string libPath)
1765
{
66+
libPath = LibPathResolver.Resolve(libName);
1867
IntPtr libPtr;
1968

2069
if (IsWindows)
@@ -27,8 +76,7 @@ public static IntPtr LoadLib(string libPath)
2776
}
2877
else if (IsMacOS)
2978
{
30-
const int RTLD_NOW = 2;
31-
libPtr = DynamicLinkingMacOS.dlopen(libPath, RTLD_NOW);
79+
libPtr = DynamicLinkingMacOS.dlopen(libPath, DynamicLinkingMacOS.RTLD_NOW);
3280
}
3381
else
3482
{
@@ -143,5 +191,6 @@ public static TDelegate GetDelegate<TDelegate>(IntPtr libPtr, string symbolName,
143191
var functionPtr = pointerDereferenceFunc.Invoke(ptr);
144192
return Marshal.GetDelegateForFunctionPointer<TDelegate>(functionPtr);
145193
}
194+
#endif
146195
}
147196
}

Secp256k1.Net/Secp256k1.Native.Legacy.cs

Lines changed: 0 additions & 86 deletions
This file was deleted.

0 commit comments

Comments
 (0)