Skip to content

Commit c25dcee

Browse files
committed
chore: separate native lib + use standard dotnet runtime setup
1 parent cc9fc07 commit c25dcee

File tree

12 files changed

+308
-24
lines changed

12 files changed

+308
-24
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Google.Cloud.SpannerLib.Native
5+
{
6+
7+
internal class DisposableGoSlice : IDisposable
8+
{
9+
private readonly GCHandle? _handle;
10+
internal GoSlice GoSlice { get; }
11+
12+
internal static DisposableGoSlice Create(byte[]? value)
13+
{
14+
var (handle, length, capacity) = Pin(value);
15+
return new DisposableGoSlice(handle,
16+
new GoSlice(handle?.AddrOfPinnedObject() ?? IntPtr.Zero, length, capacity));
17+
}
18+
19+
private DisposableGoSlice(GCHandle? handle, GoSlice goSlice)
20+
{
21+
_handle = handle;
22+
GoSlice = goSlice;
23+
}
24+
25+
private static (GCHandle?, int, int) Pin(byte[]? value)
26+
{
27+
if (value is null)
28+
{
29+
return (null, 0, 0);
30+
}
31+
32+
var length = value.Length;
33+
var handle = GCHandle.Alloc(value, GCHandleType.Pinned);
34+
return (handle, length, length);
35+
}
36+
37+
public void Dispose()
38+
{
39+
_handle?.Free();
40+
}
41+
42+
}
43+
44+
internal struct GoSlice
45+
{
46+
public IntPtr Pointer;
47+
public long Length;
48+
public long Capacity;
49+
50+
internal GoSlice(IntPtr pointer, long length, long capacity)
51+
{
52+
Pointer = pointer;
53+
Length = length;
54+
Capacity = capacity;
55+
}
56+
57+
}
58+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Text;
4+
5+
namespace Google.Cloud.SpannerLib.Native
6+
{
7+
8+
internal unsafe struct GoString : IDisposable
9+
{
10+
IntPtr Pointer { get; }
11+
internal long Length;
12+
13+
internal GoString(string value)
14+
{
15+
(Pointer, Length) = StringToHGlobalUtf8(value);
16+
}
17+
18+
private static (IntPtr, int) StringToHGlobalUtf8(string? s)
19+
{
20+
if (s is null)
21+
{
22+
return (IntPtr.Zero, 0);
23+
}
24+
25+
var nb = Encoding.UTF8.GetMaxByteCount(s.Length);
26+
var ptr = Marshal.AllocHGlobal(nb);
27+
28+
var pbMem = (byte*)ptr;
29+
var nbWritten = Encoding.UTF8.GetBytes(s, new Span<byte>(pbMem, nb));
30+
31+
return (ptr, nbWritten);
32+
}
33+
34+
public void Dispose()
35+
{
36+
Marshal.FreeHGlobal(Pointer);
37+
}
38+
}
39+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.1</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
7+
<LangVersion>9</LangVersion>
8+
<PackageId>Experimental.SpannerLib.Native</PackageId>
9+
<Title>Experimental native library for Spanner</Title>
10+
<Authors />
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<None Include="libraries/linux-x64/spannerlib.so" Pack="true" PackagePath="runtimes/linux-x64/native/" />
15+
<None Include="libraries/osx-arm64/spannerlib.dylib" Pack="true" PackagePath="runtimes/osx-arm64/native/" />
16+
</ItemGroup>
17+
18+
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace Google.Cloud.SpannerLib.Native
2+
{
3+
internal unsafe struct Message
4+
{
5+
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
6+
public long Pinner;
7+
public int Code;
8+
public long ObjectId;
9+
public int Length;
10+
public void* Pointer;
11+
#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value
12+
}
13+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using System;
2+
using System.Data;
3+
using System.Text;
4+
5+
namespace Google.Cloud.SpannerLib.Native
6+
{
7+
8+
internal class MessageHandler : IDisposable
9+
{
10+
private Message Message { get; }
11+
12+
internal long Length => Message.Length;
13+
14+
internal MessageHandler(Message message)
15+
{
16+
Message = message;
17+
}
18+
19+
internal int Code()
20+
{
21+
return Message.Code;
22+
}
23+
24+
internal long ObjectId()
25+
{
26+
return Message.ObjectId;
27+
}
28+
29+
internal bool HasError()
30+
{
31+
return Message.Code != 0;
32+
}
33+
34+
internal string? Error()
35+
{
36+
if (!HasError())
37+
{
38+
return null;
39+
}
40+
41+
return ValueAsString();
42+
}
43+
44+
internal string ValueAsString()
45+
{
46+
unsafe
47+
{
48+
Span<byte> tmp = new(Message.Pointer, Message.Length);
49+
return Encoding.UTF8.GetString(tmp);
50+
}
51+
}
52+
53+
internal unsafe ReadOnlySpan<byte> Value()
54+
{
55+
return new(Message.Pointer, Message.Length);
56+
}
57+
58+
public void Dispose()
59+
{
60+
var code = SpannerLib.Release(Message.Pinner);
61+
if (code != 0)
62+
{
63+
throw new DataException("Failed to release message");
64+
}
65+
}
66+
}
67+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using System.Runtime.CompilerServices;
2+
using System.Runtime.InteropServices;
3+
4+
[assembly: InternalsVisibleTo("Google.Cloud.SpannerLib")]
5+
6+
namespace Google.Cloud.SpannerLib.Native
7+
{
8+
public static class SpannerLib
9+
{
10+
private const string SpannerLibName = "spannerlib";
11+
12+
[DllImport(SpannerLibName, EntryPoint = "Release")]
13+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
14+
internal static extern int Release(long pinner);
15+
16+
[DllImport(SpannerLibName, EntryPoint = "CreatePool")]
17+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
18+
internal static extern Message CreatePool(GoString dsn);
19+
20+
[DllImport(SpannerLibName, EntryPoint = "ClosePool")]
21+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
22+
internal static extern Message ClosePool(long poolId);
23+
24+
[DllImport(SpannerLibName, EntryPoint = "CreateConnection")]
25+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
26+
internal static extern Message CreateConnection(long poolId);
27+
28+
[DllImport(SpannerLibName, EntryPoint = "CloseConnection")]
29+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
30+
internal static extern Message CloseConnection(long poolId, long connectionId);
31+
32+
[DllImport(SpannerLibName, EntryPoint = "Apply")]
33+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
34+
internal static extern Message Apply(long poolId, long connectionId, GoSlice mutations);
35+
36+
[DllImport(SpannerLibName, EntryPoint = "BufferWrite")]
37+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
38+
internal static extern Message BufferWrite(long poolId, long connectionId, long transactionId,
39+
GoSlice mutations);
40+
41+
[DllImport(SpannerLibName, EntryPoint = "Execute")]
42+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
43+
internal static extern Message Execute(long poolId, long connectionId, GoSlice statement);
44+
45+
[DllImport(SpannerLibName, EntryPoint = "ExecuteTransaction")]
46+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
47+
internal static extern Message ExecuteTransaction(long poolId, long connectionId, long txId, GoSlice statement);
48+
49+
[DllImport(SpannerLibName, EntryPoint = "ExecuteBatchDml")]
50+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
51+
internal static extern Message ExecuteBatchDml(long poolId, long connectionId, GoSlice statements);
52+
53+
[DllImport(SpannerLibName, EntryPoint = "Metadata")]
54+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
55+
internal static extern Message Metadata(long poolId, long connectionId, long rowsId);
56+
57+
[DllImport(SpannerLibName, EntryPoint = "ResultSetStats")]
58+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
59+
internal static extern Message ResultSetStats(long poolId, long connectionId, long rowsId);
60+
61+
[DllImport(SpannerLibName, EntryPoint = "Next")]
62+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
63+
internal static extern Message Next(long poolId, long connectionId, long rowsId);
64+
65+
[DllImport(SpannerLibName, EntryPoint = "CloseRows")]
66+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
67+
internal static extern Message CloseRows(long poolId, long connectionId, long rowsId);
68+
69+
[DllImport(SpannerLibName, EntryPoint = "BeginTransaction")]
70+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
71+
internal static extern Message BeginTransaction(long poolId, long connectionId, GoSlice transactionOptions);
72+
73+
[DllImport(SpannerLibName, EntryPoint = "Commit")]
74+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
75+
internal static extern Message Commit(long poolId, long connectionId, long txId);
76+
77+
[DllImport(SpannerLibName, EntryPoint = "Rollback")]
78+
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
79+
internal static extern Message Rollback(long poolId, long connectionId, long txId);
80+
}
81+
}
Binary file not shown.
Binary file not shown.

spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib/AbstractLibObject.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Runtime.CompilerServices;
32

43
namespace Google.Cloud.SpannerLib
54
{

spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib/Google.Cloud.SpannerLib.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
<Authors></Authors>
99
<Description>Experimental .NET library for Spanner</Description>
1010
<PackageId>Experimental.SpannerLib</PackageId>
11-
<Version>1.0.1</Version>
11+
<Version>1.0.2</Version>
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15+
<PackageReference Include="Experimental.SpannerLib.Native" Version="1.0.0" />
1516
<PackageReference Include="Google.Cloud.Spanner.Admin.Database.V1" Version="5.0.0" />
1617
<PackageReference Include="Google.Cloud.Spanner.V1" Version="5.0.0" />
1718
</ItemGroup>
@@ -28,5 +29,10 @@
2829
<pack>true</pack>
2930
</Content>
3031
</ItemGroup>
32+
33+
<ItemGroup>
34+
<None Include="native/linux-x64/spannerlib.so" Pack="true" PackagePath="runtimes/linux-x64/native/" />
35+
<None Include="native/osx-arm64/spannerlib.dylib" Pack="true" PackagePath="runtimes/osx-arm64/native/" />
36+
</ItemGroup>
3137

3238
</Project>

0 commit comments

Comments
 (0)