{"id":16974796,"url":"https://github.com/3f/conari","last_synced_at":"2025-04-05T03:04:36.111Z","repository":{"id":58260732,"uuid":"64471534","full_name":"3F/Conari","owner":"3F","description":"🧬 One-touch unmanaged memory, runtime dynamic use of the unmanaged native C/C++ in .NET world, related P/Invoke features, and …","archived":false,"fork":false,"pushed_at":"2024-11-07T00:42:09.000Z","size":874,"stargazers_count":260,"open_issues_count":5,"forks_count":28,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-03-29T02:04:19.345Z","etag":null,"topics":["accessor","binary-data","binding","conari","cpp","dll","dllexport","dllimport","hack","interop","libraries","memory","native","pe32","pe32-plus","pinvoke","pinvoke-wrapper","runtime","unmanaged","winapi"],"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/3F.png","metadata":{"files":{"readme":"Readme.md","changelog":"changelog.txt","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","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},"funding":{"custom":["3F.github.io/fund"]}},"created_at":"2016-07-29T10:11:22.000Z","updated_at":"2025-03-18T15:18:05.000Z","dependencies_parsed_at":"2025-02-24T16:11:59.563Z","dependency_job_id":"d9b22689-d1e9-4116-a2d3-9bc6cf9fdc2a","html_url":"https://github.com/3F/Conari","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FConari","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FConari/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FConari/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/3F%2FConari/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/3F","download_url":"https://codeload.github.com/3F/Conari/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247280262,"owners_count":20912967,"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","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":["accessor","binary-data","binding","conari","cpp","dll","dllexport","dllimport","hack","interop","libraries","memory","native","pe32","pe32-plus","pinvoke","pinvoke-wrapper","runtime","unmanaged","winapi"],"created_at":"2024-10-14T01:08:08.885Z","updated_at":"2025-04-05T03:04:36.090Z","avatar_url":"https://github.com/3F.png","language":"C#","readme":"# [Conari](https://github.com/3F/Conari)\n\n[![](https://raw.githubusercontent.com/3F/Conari/master/Conari/Resources/Conari_v1.png)](https://github.com/3F/Conari)\n\n🧬 An unmanaged memory, modules, and raw data in *one-touch*.\n\nConari engine represents most flexible platform for working with unmanaged memory, modules, related P/Invoke features, and more around libraries, executable modules, runtime dynamic use of the unmanaged native C/C++ in .NET world and other raw data just in a few easy steps without configuring something, and... Even accessing to complex types like structures without their declaration at all.\n\n```\nCopyright (c) 2016-2024  Denis Kuzmin \u003cx-3F@outlook.com\u003e github/3F\n```\n\n[ 「 ❤ 」 ](https://3F.github.io/fund) [![License](https://img.shields.io/badge/License-MIT-74A5C2.svg)](https://github.com/3F/Conari/blob/master/LICENSE.txt)\n\n[*Conari*](https://github.com/3F/Conari) is waiting for your awesome contributions! https://github.com/3F/Conari/graphs/contributors\n\n[![Build status](https://ci.appveyor.com/api/projects/status/xbb5imyn9lr8dxbb/branch/master?svg=true)](https://ci.appveyor.com/project/3Fs/conari-wkygr/branch/master)\n[![GHR](https://img.shields.io/github/release/3F/Conari.svg)](https://github.com/3F/Conari/releases/latest)\n[![NuGet](https://img.shields.io/nuget/v/Conari.svg)](https://www.nuget.org/packages/Conari/) \n[![Tests](https://img.shields.io/appveyor/tests/3Fs/conari-wkygr/master.svg)](https://ci.appveyor.com/project/3Fs/conari-wkygr/build/tests)\n\n[**`gnt`**](https://3F.github.io/GetNuTool/releases/latest/gnt/)` Conari` [[?](https://github.com/3F/GetNuTool)]\n\n## Why Conari\n\n\u003e [ ***[Quick start (Wiki)](https://github.com/3F/Conari/wiki/Quick-start)*** ] [ [Complex types and strings](https://www.youtube.com/watch?v=QXMj9-8XJnY) ]\n\n[![](https://raw.githubusercontent.com/3F/Conari/master/Conari/Resources/screencast_Complex_types.jpg)](https://www.youtube.com/watch?v=QXMj9-8XJnY)\n\n\nIt was designed to be loyal to your needs on the fly!\n\n🔍 Easy to start\n\n```csharp\nusing ConariL l = new(\"...\");\n```\n\n🧰 Powerful types\n\nNo more manual type conversions and memory management complexities. Because nothing easier than just use it,\n\n[`[⏯]`](https://github.com/3F/Conari/blob/4b17df2a4efd0a5fae4f3498dbe7327db5e43d22/ConariTest/BindingContextTest.cs#L20-L24)\n```csharp\nusing dynamic l = new ConariX(\"regXwild.dll\");\n\nstring data = \"number = 888;\";\nbool found = l.replace\u003cbool\u003e(ref data, \"+??;\", \"2034;\");\n// found: true; data: number = 2034;\n```\n\n🔨 Its amazing DLR features\n\n```csharp\nusing dynamic l = new ConariX(\"...\");\nl.\u003cwhatever_you_want\u003e(curl, 10002, \"https://\");\n```\n\nStill not convinced? Here's full workable code example for [regXwild](https://github.com/3F/regXwild):\n\n```csharp\nusing var c = ConariL.Make(new(\"regXwild\"), out dynamic l);\n// ready for everything even without configuring\n\nusing var u = NativeStruct.Make.f\u003cUIntPtr\u003e(\"start\", \"end\").Struct;\n/* Hey! We just generated a structure like\n[StructLayout(LayoutKind.Sequential)]\nprivate struct MatchResult\n{\n    public UIntPtr start;\n    public UIntPtr end;\n}*/\n\nif(l.match\u003cbool\u003e(\"n = '888';\", \"'*'\", 2/*MATCH_RESULT*/, u))\n{\n    /* Now we just generated and invoked this\n    REGXWILD_API_L bool match\n    (\n        const rxwtypes::TCHAR* input,\n        const rxwtypes::TCHAR* pattern,\n        rxwtypes::flagcfg_t options,\n        EssRxW::MatchResult* result\n    )\n    */\n    dynamic v = u.Access; // just access the EssRxW::MatchResult* result\n    // v.start == 4; v.end == 9;\n}\n// Yes, a 4 lines and your task is done; Free memory, Free hands.\n```\n\n[`[⏯]`](https://github.com/3F/DllExport/blob/master/src/DllExport/assets/NetfxAsset/Basic.cs) DllExport + Conari\n\n```csharp\n[DllExport] // DllExportModifiedClassLibrary.dll\npublic static IntPtr callme(TCharPtr str, IntPtr structure)\n{\n    if(str != \"Hello world!\") return IntPtr.Zero;\n\n    structure.Native().f\u003cint\u003e(\"x\", \"y\").build(out dynamic v);\n    if(v.x \u003e v.y)\n    {\n        structure.Access().write\u003cint\u003e(8);\n    }\n    return new NativeArray\u003cint\u003e(-1, v.x, 1, v.y);\n}\n```\n\n[`[⏯]`](https://github.com/3F/DllExport/blob/master/src/DllExport/UnitedTest/NetfxAssetBasicTest.cs)\n\n```csharp\n... // host side via C/C++, Java, Rust, Python, ... or even same dotnet C#\nusing NativeString\u003cTCharPtr\u003e ns = new(\"Hello world!\");\nusing NativeStruct\u003cArg\u003e nstruct = new(new Arg() { x = 7, y = 5 });\n\nusing dynamic l = new ConariX(\"DllExportModifiedClassLibrary.dll\");\nIntPtr ptr = l.callme\u003cIntPtr\u003e(ns, nstruct);\n\nusing NativeArray\u003cint\u003e nr = new(4, ptr); // (nstruct.Data.x == 8) != (nr[1] == 7)\n```\n\n🚀 Awesome speed\n\nOptional caching of 0x29 opcodes (Calli) and more.\n\ntest of regXwild's algorithms [[340x10000 Unicode](https://github.com/3F/regXwild#speed)]   | +icase [x32]| +icase [x64]         | `\n----------------------------------------------|--------------|-----------------|---\nregXwild **native C++** `EXT` algorithm       | **~50ms**    | **~26ms**       | `\u003c\u003c`\nregexp-c++11(regex_search)                    | ~59309ms     | ~53334ms        |\nregexp-c++11(regex_match with endings .*)     | ~59503ms     | ~53817ms        |\n.NET Regex engine [Compiled]                  | ~38310ms     | ~37242ms        |\n.NET Regex engine                             | ~31565ms     | ~30975ms        |\nregXwild via **Conari** v1.3 (Lambda) - `EXT` | **~54ms**    | **~35ms**       | `\u003c\u003c`\nregXwild via **Conari** v1.3 (DLR) - `EXT`    | ~214ms       | ~226ms          |\n\n🔧 The easiest (most ever) access to any data in unmanaged memory\n\n```csharp\n// Everything will be generated at runtime\nmemory.Native()\n    .f\u003cWORD\u003e(\"Machine\", \"NumberOfSections\") // IMAGE_FILE_HEADER (0xF4)\n    .align\u003cDWORD\u003e(3)\n    .t\u003cWORD\u003e(\"SizeOfOptionalHeader\")\n    .t\u003cWORD\u003e(\"Characteristics\")\n    .region()\n    .t\u003cWORD\u003e(\"Magic\") // IMAGE_OPTIONAL_HEADER (0x108)\n    .build(out dynamic ifh);\n\nif(ifh.SizeOfOptionalHeader == 0xF0) { // IMAGE_OPTIONAL_HEADER64\n    memory.move(0x6C);\n}\n\n// Use it !\n\nifh.NumberOfSections // 6\nifh.Characteristics  // IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE | IMAGE_FILE_DLL\nifh.Machine          // IMAGE_FILE_MACHINE_AMD64\nifh.Magic            // PE64\n```\n\n```csharp\ndynamic l = ptr.Native().f\u003cint\u003e(\"x\", \"y\").build();\nl.x // 17\nl.y // -23\n```\n\n🏄 Most powerful PInvoke and even most convenient use of WinAPI without preparing something\n\nConari will generate and adapt everything at runtime! Specially for you! For example, below we don't provide neither *user32.ShowWindow()* nor *user32.MessageBoxA(),* even no *kernel32.GetModuleHandleA/W()*\n\n```csharp\ndynamic user32 = new User32();\n\n    user32.ShowWindow(0x000A0A28, 3);\n    user32.MessageBoxA(0, \"Conari in action\", \"Hello!\", 0);\n```\n\n```csharp\ndynamic kernel32 = new Kernel32();\n\n    kernel32.GetModuleHandleA\u003cIntPtr\u003e(\"libcurl-x64\");\n    kernel32.GetModuleHandleW\u003cIntPtr\u003e((WCharPtr)ustr);\n```\n\nBecause our recipe is simple, *Just use it!* and have fun.\n\n🔖 Modern **.NET Core**\n\nConari is ready for .NET Core starting from 1.4. Even for [.NET Standard **2.0**](https://github.com/3F/Conari/issues/13) which does not cover unmanaged *EmitCalli* due to missing implementation for *System.Private.CoreLib.* Now this is another one of independent solution for everyone as https://github.com/3F/UnmanagedEmitCalli\n\n🍰 **Open and Free**\n\nOpen Source project; MIT License; *Fork! Star! Contribute! Share! Enjoy!*\n\nConari is available for everyone from 2016 🎉\n\n## [Take a look closer](https://github.com/3F/Conari/wiki/Quick-start)\n\nConari generally provides two mode,\n\n*Fully automatic* way through its dynamic features (**DLR**). For example, when using the *unmanaged* code:\n\n```csharp\nvar ptr     = d.test\u003cIntPtr\u003e(); //lambda ~ bind\u003cFunc\u003cIntPtr\u003e\u003e(\"test\")();\nvar codec   = d.avcodec_find_encoder\u003cIntPtr\u003e(AV_CODEC_ID_MP2); //lambda ~ bind\u003cFunc\u003culong, IntPtr\u003e\u003e(\"avcodec_find_encoder\")(AV_CODEC_ID_MP2);\n              d.push(); //lambda ~ bind\u003cAction\u003e(\"push\")();\n              d.create\u003cint\u003e(ref cid, out data); //lambda ~ bind\u003cMyFunc\u003cGuid, object\u003e\u003e(\"create\")(ref cid, out data);\n```\n\nThis (or like) does not require the any configuration from you, because Conari will do it **automatically**.\n\n*Semi-automatic* way through its custom **lambda expressions**. For example, when using the *unmanaged* code:\n\n```csharp\nusing(var l = new ConariL(\"Library.dll\"))\n{\n    l.bind\u003cAction\u003cint, int\u003e\u003e(\"call\")(2, 1); \n    double num = l.bind\u003cFunc\u003cIntPtr, int, double\u003e\u003e(\"tonumber\")(L, 4);\n}\n```\n\nThis also does not require neither the creation of any additional delegates nor the configuring something. Just a more control through `l.bind\u003c...\u003e(\"...\")` methods that still make you happy;\n\n```csharp\n// invoke it immediately\nl.bind\u003cAction\u003cint, string\u003e\u003e(\"set\")(-1, \"Hello from Conari !\");\n\n// or later\nset(-1, \"Hello from Conari !\");\n```\n\n**Native C/C++ structures without declaration** **[[?](https://github.com/3F/Conari/issues/2)]**:\n\n```csharp\n// IMAGE_FILE_HEADER: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313.aspx\ndynamic ifh = binaryData.Native()\n            .t\u003cWORD, WORD\u003e(null, \"NumberOfSections\")\n            .align\u003cDWORD\u003e(3)\n            .t\u003cWORD, WORD\u003e(\"SizeOfOptionalHeader\")\n            .build();\n                \nif(ifh.SizeOfOptionalHeader == 0xF0) { // IMAGE_OPTIONAL_HEADER64\n    ... \n}\n\n// IMAGE_DATA_DIRECTORY: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680305.aspx\nbinaryData.Native()\n    .t\u003cDWORD\u003e(\"VirtualAddress\")\n    .t\u003cDWORD\u003e(\"Size\")\n    .build(out dynamic idd);\n\nDWORD offset = rva2Offset(idd.VirtualAddress);\n```\n\n```csharp\nIntPtr ptr ...\nRaw mt = ptr.Native()\n            .align\u003cint\u003e(2, \"a\", \"b\")\n            .t\u003cIntPtr\u003e(\"name\")\n            .Raw;\n            \n-     {byte[0x0000000c]} byte[]\n        [0]    0x05    byte --\n        [1]    0x00    byte   |\n        [2]    0x00    byte   |\n        [3]    0x00    byte --^ a = 5\n        [4]    0x07    byte --\n        [5]    0x00    byte   |\n        [6]    0x00    byte   |\n        [7]    0x00    byte --^ b = 7\n        [8]    0x20    byte --\n        [9]    0x78    byte   |_ pointer to allocated string: (CharPtr)name\n        [10]   0xf0    byte   |\n        [11]   0x56    byte --\n...\n```\n\nA modern *NativeData* chains for everything (Memory, Streams, Local collections, ...)\n\n```csharp\n.move(0x3C, Zone.D)\n.read(out LONG e_lfanew)\n.move(e_lfanew, Zone.D)\n.eq('P', 'E', '\\0', '\\0')\n.ifFalse(_ =\u003e throw new PECorruptDataException())\n.Native()\n.f\u003cWORD\u003e(\"Machine\", \"NumberOfSections\")\n.align\u003cDWORD\u003e(3)\n.t\u003cWORD, WORD\u003e(\"SizeOfOptionalHeader\", \"Characteristics\")\n.region()\n.t\u003cWORD\u003e(\"Magic\") // start IMAGE_OPTIONAL_HEADER offset 0 (0x108)\n.build(out dynamic ifh)\n.Access\n.move(ifh.SizeOfOptionalHeader == 0xF0 ? 0x6C : 0x5C)\n.read(out DWORD NumberOfRvaAndSizes)\n.Native() // DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]\n.t\u003cDWORD\u003e(\"VirtualAddress\")\n.t\u003cDWORD\u003e(\"Size\")\n.build(out dynamic idd)\n.Access.move(8 * (NumberOfRvaAndSizes - 1))\n...\n\n// ifh.Machine;          - IMAGE_FILE_MACHINE_AMD64\n// e_lfanew              - 0x110\n// NumberOfRvaAndSizes   - 16\n// idd.VirtualAddress    - VA 0x7070\n// ifh.Characteristics;  - IMAGE_FILE_EXECUTABLE_IMAGE \n//                          | IMAGE_FILE_LARGE_ADDRESS_AWARE \n//                          | IMAGE_FILE_DLL\n// ifh.Magic;            - PE64\n// ifh.NumberOfSections; - 6\n// ...\n```\n\n**Calling Convention** \u0026 **Name-Decoration** **[[?](https://github.com/3F/Conari/issues/3)]**\n\n```csharp\nusing(var l = new ConariL(\"Library.dll\", CallingConvention.StdCall))\n{\n    //...\n    l.Mangling = true; // _get_SevenStdCall@0 \u003c-\u003e get_SevenStdCall\n    l.Convention = CallingConvention.Cdecl;\n}\n```\n\n**Exported Variables** [[?](https://github.com/3F/Conari/issues/7#issuecomment-269123650)] \u0026 **raw accessing** [[?](https://github.com/3F/Conari/issues/17#issuecomment-716176288)]\n\n```csharp\nl._.ADDR_SPEC // DLR, 0x00001CE8\nl.V.get\u003cUInt32\u003e(\"ADDR_SPEC\"); // lambda, 0x00001CE8\nstd_cin = l.addr(\"?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A\");\n```\n\n**Aliases [[?](https://github.com/3F/Conari/issues/9#issuecomment-273855381)]**\n\n```csharp\n// v1.3+\nl.Aliases[\"Flag\"] = l.Aliases[\"getFlag\"] = l.Aliases[\"xFunc\"]; //Flag() -\u003e getFlag() -\u003e xFunc()-\u003e...\n// ...\nl._.getFlag\u003cbool\u003e();\n```\n\n**Additional types**\n\n* TCharPtr, CharPtr, WCharPtr, float_t, int_t, ptrdiff_t, size_t, uint_t, ...\n* NativeString\\\u003cT\\\u003e (+NativeStringManager\\\u003cT\\\u003e) - Fully supports TCharPtr, CharPtr, WCharPtr;\n* NativeStruct - Fully automatic way of working with structures without declarations using NativeData chains;\n* NativeStruct\\\u003cT\\\u003e - Semi-automatic way of working with structures using CLR types declarations;\n* NativeArray\\\u003cT\\\u003e\n* ._T(\"...\") - NativeString\\\u003cTCharPtr\\\u003e via NativeStringManager\\\u003cTCharPtr\\\u003e\n* ...\n\n```csharp\nusing var a = new NativeString\u003cWCharPtr\u003e(\"Hello\");\nusing var b = a + \" world!\"; // unmanaged C-string, a Unicode characters\n```\n\n```csharp\nCharPtr name = c.to\u003cCharPtr\u003e(1, out size_t len);\n//CharPtr name = c.bind\u003cFuncOut3\u003cint, size_t, IntPtr\u003e\u003e(\"to\")(1, out size_t len);\nstring myName += name; // 8 bit C-string and managed string (UTF-16)\n```\n\n```csharp\nusing NativeArray\u003cshort\u003e nr = new(pointer); // points to ~0x2674F89EDF0\nnr[0] = 1; nr[1] = 2;\n```\n```csharp\nusing NativeArray\u003cint\u003e nr = new(1, 2, 3);\nnr[0] = -1;\nnr[1] = 0;\nnr[2] = 1;\n\nAssert.True(nr == new int[] { -1, 0, 1 });\n```\n\n```csharp\nusing var u = new NativeStruct\u003cMatchResult\u003e();\nl.match\u003cbool\u003e(\n    \"[system]\", \"Sys###\", \n    EngineOptions.F_ICASE | EngineOptions.F_MATCH_RESULT, \n    u\n);\nu.Data.start // 1\nu.Data.end   // 7\n```\n\n```csharp\nusing ConariL l = new(\"regXwild.dll\");\nl._.replace\u003cbool\u003e\n(\n    l._T(\"number = 888;\", out CharPtr result), \n    l._T(\"+??;\"), l._T(\"2034;\")\n);\n// result: number = 2034;\n```\n\n```csharp\nusing dynamic l = new ConariX(RXW_X);\n\nbool found = l.replace\u003cbool\u003e\n(\n    \"Hello {p}\".Do(out TCharPtr result),\n    \"{p}\",\n    \"world!\"\n); // found: true; result: Hello world!\n```\n\nand more ...\n\n\n### [✏ Examples](https://github.com/3F/Conari/wiki/Examples)\n\nHow about [regXwild](https://github.com/3F/regXwild) (⏱ Superfast ^Advanced wildcards++? on native unmanaged C++) in your C# code?\n\n```csharp\nusing dynamic l = new ConariX(\"regXwild.dll\");\nif(l.match\u003cbool\u003e(input, \"'+.#?'\")) {\n    // ... '1.4', '1.04', ...\n}\n```\nYes, you don't need to do anything else! Conari will prepare everything for binding with the following native method instead of you:\n\n```cpp\nREGXWILD_API_L bool match\n(\n    const rxwtypes::TCHAR* input,\n    const rxwtypes::TCHAR* pattern,\n    rxwtypes::flagcfg_t options = 0,\n    EssRxW::MatchResult* result = nullptr\n);\n```\n","funding_links":["3F.github.io/fund"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3f%2Fconari","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F3f%2Fconari","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F3f%2Fconari/lists"}