MemoryLock 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package MemoryLock --version 1.0.0
NuGet\Install-Package MemoryLock -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MemoryLock" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MemoryLock --version 1.0.0
#r "nuget: MemoryLock, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MemoryLock as a Cake Addin
#addin nuget:?package=MemoryLock&version=1.0.0

// Install MemoryLock as a Cake Tool
#tool nuget:?package=MemoryLock&version=1.0.0

Memory Lock

Build Status nuget license

<p align="center"> <img src="image/icon_256.png"/> </p>

Allocate memories in C# by using "using" statement.

What is this ?

This is a wrapper library for :

  • System.Runtime.InteropServices.Marshal.AllocCoTaskMem
  • System.Runtime.InteropServices.Marshal.FreeCoTaskMem
  • System.Runtime.InteropServices.Marshal.AllocHGlobal
  • System.Runtime.InteropServices.Marshal.Marshal.FreeHGlobal
  • System.Runtime.InteropServices.GCHandle.Alloc
  • System.Runtime.InteropServices.GCHandle.Free

They are used for allocating memories which is never collected or moved by GC (Garbage Collector).
People use these functions when they want to call native codes by P/Invoke because passing some parameters to C++ requires to prepare memories not moved.

Why wrap them ?

After allocating memories, we have to release them.
It is so bothered. Isn't it ?
That is why I implemented this library.
Using Memory Lock, you don't have to pay attention to memories whether they are released or not.

Watch the following code :

// using System.Runtime.InteropServices;

// Allocate memories by "size"
var pointer = Marshal.AllocCoTaskMem(size);

//
// Do something
//

// Release memories
Marshal.FreeCoTaskMem(pointer);

// "pointer" refers to nothing but the parameter alives.
// If you use "pointer" here, it will cause "undefined behaviour".

This is an ordinary code using Marshal.AllocCoTaskMem.
I think it has some problems :

  • When you forget to write Free(), It is too difficult to realize the mistake.
  • You can access the pointer which is released easily.

With Memory Lock, you can write the following code :

// using CapraLib.MemoryLock;

// Allocate memories
using(var allocated = new CoTaskMemAllocater(out var pointer, size))
{
    // Do something
}

// You can't access to the pointer here !
// And they are already released !

This library solves the problems clearly !
In C# 8, you can use this with "using declarations".

Examples

Allocate 100 bytes

using(var allocated = new CoTaskMemAllocater(out var pointer, 100))
// OR
using(var allocated = new HGlobalAllocater(out var pointer, 100))
{
    // Do something with "pointer" !
}

The following table will help you.

Allocate memory by ... Size Object(Non type) Unmanaged object
CoTaskMemAllocater ✔️
HGlobalAllocater ✔️
GCAllocater ✔️
CoTaskMemAllocater<T> ✔️
HGlobalAllocater<T> ✔️
GCAllocater<T> ✔️

Unmanaged object includes :

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool
  • User defined structs which has attribute, [StructLayout(LayoutKind.Sequential)]

Using struct

If you have a struct :

// StructLayout should be LayoutKind.Sequential
// when it is used in Memory Lock
[StructLayout(LayoutKind.Sequential)]
public struct Vector
{
    public float x;
    public float y;
    public float z;
}

And a native function :

// Assign values to vec
[DllImport("Some.dll")]
static extern void ChangeAll(IntPtr vec, float x, float y, float z);

On that time, you can write the following code :

// using CaprLib.MemoryLock;

var vec = new Vector();
vec.x = 10f;

using(var allocated = new CoTaskMemAllocater<Vector>(out var pointer, vec))
{
    // Assign another values to the pointer
    ChangeAll(pointer, 15f, 19f, 23f);

    // Copy from unmanaged memory to managed.
    allocated.SetResult(out vec);
}

Console.WriteLine($"vec.x = {vec.x}"); // vec.x = 15

Before releasing the memory, you can call void SetResults(out T vec) to save changes to managed items.
This function is implemented in

  • CoTaskMemAllocater<T>
  • HGlobalAllocater<T>
  • GCAllocater<T>

Author

capra314cabra

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.1 is compatible.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.0 560 9/9/2019
1.1.0 453 9/4/2019
1.0.0 457 8/31/2019
1.0.0-beta 325 8/23/2019