https://github.com/caphosra/memorylock
With this library, you can pin the managed object or allocate the memory easily. And you never forget releasing them.
https://github.com/caphosra/memorylock
csharp csharp-library dotnet dotnet-core dotnet-library marshalling memory memory-leak memory-lock nuget nuget-package nuget-packages p-invoke pinvoke pinvoke-wrapper span
Last synced: 5 months ago
JSON representation
With this library, you can pin the managed object or allocate the memory easily. And you never forget releasing them.
- Host: GitHub
- URL: https://github.com/caphosra/memorylock
- Owner: caphosra
- License: mit
- Created: 2019-08-22T13:55:07.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2020-03-22T13:05:10.000Z (almost 6 years ago)
- Last Synced: 2025-10-02T19:33:30.786Z (5 months ago)
- Topics: csharp, csharp-library, dotnet, dotnet-core, dotnet-library, marshalling, memory, memory-leak, memory-lock, nuget, nuget-package, nuget-packages, p-invoke, pinvoke, pinvoke-wrapper, span
- Language: C#
- Homepage:
- Size: 72.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Memory Lock
[](https://dev.azure.com/capra314cabra/MemoryLock/_build/latest?definitionId=5&branchName=master)
[](https://www.nuget.org/packages/MemoryLock/)
[](https://github.com/capra314cabra/MemoryLock/blob/master/LICENSE)
[](https://dev.azure.com/capra314cabra/MemoryLock/_build/latest?definitionId=5&branchName=master)
[](https://github.com/capra314cabra/MemoryLock)
With this library, you can pin the managed object or allocate the memory easily.
And you __never__ forget releasing them.
## 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.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 :
``` C#
// 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 :
``` C#
// using CapraLib.MemoryLock;
// Allocate memories
using(var allocated = new MemoryAllocater(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"](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations).
## Examples
### Allocate 100 bytes
``` C#
using(var allocated = new MemoryAllocater(out var pointer, 100))
{
// Do something with "pointer" !
}
```
The following table will help you.
| Allocate memory by ... | Size | Unmanaged object |
|---|:---:|:---:|
| CoTaskMemAllocater | :heavy_check_mark: |
| HGlobalAllocater | :heavy_check_mark: |
| CoTaskMemAllocater<T> || :heavy_check_mark: |
| HGlobalAllocater<T> || :heavy_check_mark: |
| GCAllocater<T> || :heavy_check_mark: |
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 :
``` C#
// 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 :
``` C#
// 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 :
``` C#
// using CaprLib.MemoryLock;
var vec = new Vector();
vec.x = 10f;
using(var allocated = new MemoryAllocater(out var pointer, vec))
{
// Assign another values to the pointer
ChangeAll(pointer, 15f, 19f, 23f);
// Copy from unmanaged memory to managed.
allocated.CopyTo(out vec);
}
Console.WriteLine($"vec.x = {vec.x}"); // vec.x = 15
```
Before releasing the memory, you can call `void CopyTo(out T obj)` to save changes to managed items.
This function is implemented in
- `MemoryAllocater`
- `CoTaskMemAllocater`
- `HGlobalAllocater`
- `GCAllocater`
### Do so without CopyTo()
You can forget writing CopyTo().
If you want to save changes automatically, I recommend you to use `MemoryLock.AsNative(ref T, MemoryAllocationHandle)`.
This is a example for `MemoryLock.AsNative` :
``` C#
var result = new Vector();
MemoryLock.AsNative(ref result, (ptr) =>
{
// Do something with pointer !
});
// "result" is now reflected the changes.
```
## Author
[capra314cabra](https://github.com/capra314cabra)