{"id":24103325,"url":"https://github.com/caphosra/memorylock","last_synced_at":"2025-10-05T16:10:30.445Z","repository":{"id":105893671,"uuid":"203805799","full_name":"caphosra/MemoryLock","owner":"caphosra","description":"With this library, you can pin the managed object or allocate the memory easily. And you never forget releasing them.","archived":false,"fork":false,"pushed_at":"2020-03-22T13:05:10.000Z","size":74,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-02T19:33:30.786Z","etag":null,"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"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/caphosra.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-22T13:55:07.000Z","updated_at":"2020-03-22T12:26:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"e69a63af-47e7-48b3-ad81-df19de9bef71","html_url":"https://github.com/caphosra/MemoryLock","commit_stats":null,"previous_names":["capra314cabra/memorylock"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/caphosra/MemoryLock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caphosra%2FMemoryLock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caphosra%2FMemoryLock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caphosra%2FMemoryLock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caphosra%2FMemoryLock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/caphosra","download_url":"https://codeload.github.com/caphosra/MemoryLock/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caphosra%2FMemoryLock/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278478756,"owners_count":25993719,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["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"],"created_at":"2025-01-10T19:56:17.771Z","updated_at":"2025-10-05T16:10:30.416Z","avatar_url":"https://github.com/caphosra.png","language":"C#","readme":"# Memory Lock\n\n[![Build Status](https://dev.azure.com/capra314cabra/MemoryLock/_apis/build/status/capra314cabra.MemoryLock?branchName=master)](https://dev.azure.com/capra314cabra/MemoryLock/_build/latest?definitionId=5\u0026branchName=master)\n[![nuget](https://img.shields.io/nuget/v/MemoryLock)](https://www.nuget.org/packages/MemoryLock/)\n[![license](https://img.shields.io/github/license/capra314cabra/MemoryLock)](https://github.com/capra314cabra/MemoryLock/blob/master/LICENSE)\n[![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/capra314cabra/MemoryLock/5)](https://dev.azure.com/capra314cabra/MemoryLock/_build/latest?definitionId=5\u0026branchName=master)\n[![GitHub stars](https://img.shields.io/github/stars/capra314cabra/MemoryLock?style=social)](https://github.com/capra314cabra/MemoryLock)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"image/icon_256.png\"/\u003e\n\u003c/p\u003e\n\nWith this library, you can pin the managed object or allocate the memory easily.   \nAnd you __never__ forget releasing them.\n\n## What is this ?\n\nThis is a wrapper library for :\n\n- `System.Runtime.InteropServices.Marshal.AllocCoTaskMem`\n- `System.Runtime.InteropServices.Marshal.FreeCoTaskMem`\n- `System.Runtime.InteropServices.Marshal.AllocHGlobal`\n- `System.Runtime.InteropServices.Marshal.FreeHGlobal`\n- `System.Runtime.InteropServices.GCHandle.Alloc`\n- `System.Runtime.InteropServices.GCHandle.Free`\n\nThey are used for allocating memories which is never collected or moved by GC (Garbage Collector).  \nPeople 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.\n\n## Why wrap them ?\n\n__After allocating memories, we have to release them.__  \nIt is so bothered. Isn't it ?  \nThat is why I implemented this library.  \nUsing Memory Lock, you don't have to pay attention to memories whether they are released or not.\n\nWatch the following code :\n``` C#\n// using System.Runtime.InteropServices;\n\n// Allocate memories by \"size\"\nvar pointer = Marshal.AllocCoTaskMem(size);\n\n//\n// Do something\n//\n\n// Release memories\nMarshal.FreeCoTaskMem(pointer);\n\n// \"pointer\" refers to nothing but the parameter alives.\n// If you use \"pointer\" here, it will cause \"undefined behaviour\".\n```\n\nThis is an ordinary code using `Marshal.AllocCoTaskMem`.  \nI think it has some problems : \n- When you forget to write Free(), It is too difficult to realize the mistake.\n- You can access the pointer which is released easily.\n\nWith Memory Lock, you can write the following code :\n\n``` C#\n// using CapraLib.MemoryLock;\n\n// Allocate memories\nusing(var allocated = new MemoryAllocater(out var pointer, size))\n{\n    // Do something\n}\n\n// You can't access to the pointer here !\n// And they are already released !\n```\n\nThis library solves the problems clearly !  \nIn C# 8, you can use this with [\"using declarations\"](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations).\n\n## Examples\n\n### Allocate 100 bytes\n\n``` C#\nusing(var allocated = new MemoryAllocater(out var pointer, 100))\n{\n    // Do something with \"pointer\" !\n}\n```\n\nThe following table will help you.\n\n| Allocate memory by ... | Size | Unmanaged object |\n|---|:---:|:---:|\n| CoTaskMemAllocater | :heavy_check_mark: |\n| HGlobalAllocater | :heavy_check_mark: |\n| CoTaskMemAllocater\u0026lt;T\u0026gt; || :heavy_check_mark: |\n| HGlobalAllocater\u0026lt;T\u0026gt; || :heavy_check_mark: |\n| GCAllocater\u0026lt;T\u0026gt; || :heavy_check_mark: |\n\nUnmanaged object includes : \n- `sbyte`, `byte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `char`, `float`, `double`, `decimal`, `bool`\n- User defined structs which has attribute, `[StructLayout(LayoutKind.Sequential)]`\n\n### Using struct\n\nIf you have a struct :\n\n``` C#\n// StructLayout should be LayoutKind.Sequential\n// when it is used in Memory Lock\n[StructLayout(LayoutKind.Sequential)]\npublic struct Vector\n{\n    public float x;\n    public float y;\n    public float z;\n}\n```\n\nAnd a native function : \n\n``` C#\n// Assign values to vec\n[DllImport(\"Some.dll\")]\nstatic extern void ChangeAll(IntPtr vec, float x, float y, float z);\n```\n\nOn that time, you can write the following code : \n\n``` C#\n// using CaprLib.MemoryLock;\n\nvar vec = new Vector();\nvec.x = 10f;\n\nusing(var allocated = new MemoryAllocater\u003cVector\u003e(out var pointer, vec))\n{\n    // Assign another values to the pointer\n    ChangeAll(pointer, 15f, 19f, 23f);\n\n    // Copy from unmanaged memory to managed.\n    allocated.CopyTo(out vec);\n}\n\nConsole.WriteLine($\"vec.x = {vec.x}\"); // vec.x = 15\n```\n\nBefore releasing the memory, you can call `void CopyTo(out T obj)` to save changes to managed items.  \nThis function is implemented in\n\n- `MemoryAllocater\u003cT\u003e`\n- `CoTaskMemAllocater\u003cT\u003e`\n- `HGlobalAllocater\u003cT\u003e`\n- `GCAllocater\u003cT\u003e`\n\n### Do so without CopyTo()\n\nYou can forget writing CopyTo().  \nIf you want to save changes automatically, I recommend you to use `MemoryLock.AsNative\u003cT\u003e(ref T, MemoryAllocationHandle)`.\n\nThis is a example for `MemoryLock.AsNative\u003cT\u003e` :\n\n``` C#\n\nvar result = new Vector();\n\nMemoryLock.AsNative(ref result, (ptr) =\u003e \n{\n    // Do something with pointer !\n});\n\n// \"result\" is now reflected the changes.\n\n```\n\n## Author\n\n[capra314cabra](https://github.com/capra314cabra)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaphosra%2Fmemorylock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaphosra%2Fmemorylock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaphosra%2Fmemorylock/lists"}