An open API service indexing awesome lists of open source software.

https://github.com/3f/conari

🧬 One-touch unmanaged memory, runtime dynamic use of the unmanaged native C/C++ in .NET world, related P/Invoke features, and …
https://github.com/3f/conari

accessor binary-data binding conari cpp dll dllexport dllimport hack interop libraries memory native pe32 pe32-plus pinvoke pinvoke-wrapper runtime unmanaged winapi

Last synced: 21 days ago
JSON representation

🧬 One-touch unmanaged memory, runtime dynamic use of the unmanaged native C/C++ in .NET world, related P/Invoke features, and …

Awesome Lists containing this project

README

        

# [Conari](https://github.com/3F/Conari)

[![](https://raw.githubusercontent.com/3F/Conari/master/Conari/Resources/Conari_v1.png)](https://github.com/3F/Conari)

🧬 An unmanaged memory, modules, and raw data in *one-touch*.

Conari 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.

```
Copyright (c) 2016-2024 Denis Kuzmin github/3F
```

[ 「 ❤ 」 ](https://3F.github.io/fund) [![License](https://img.shields.io/badge/License-MIT-74A5C2.svg)](https://github.com/3F/Conari/blob/master/LICENSE.txt)

[*Conari*](https://github.com/3F/Conari) is waiting for your awesome contributions! https://github.com/3F/Conari/graphs/contributors

[![Build status](https://ci.appveyor.com/api/projects/status/xbb5imyn9lr8dxbb/branch/master?svg=true)](https://ci.appveyor.com/project/3Fs/conari-wkygr/branch/master)
[![GHR](https://img.shields.io/github/release/3F/Conari.svg)](https://github.com/3F/Conari/releases/latest)
[![NuGet](https://img.shields.io/nuget/v/Conari.svg)](https://www.nuget.org/packages/Conari/)
[![Tests](https://img.shields.io/appveyor/tests/3Fs/conari-wkygr/master.svg)](https://ci.appveyor.com/project/3Fs/conari-wkygr/build/tests)

[**`gnt`**](https://3F.github.io/GetNuTool/releases/latest/gnt/)` Conari` [[?](https://github.com/3F/GetNuTool)]

## Why Conari

> [ ***[Quick start (Wiki)](https://github.com/3F/Conari/wiki/Quick-start)*** ] [ [Complex types and strings](https://www.youtube.com/watch?v=QXMj9-8XJnY) ]

[![](https://raw.githubusercontent.com/3F/Conari/master/Conari/Resources/screencast_Complex_types.jpg)](https://www.youtube.com/watch?v=QXMj9-8XJnY)

It was designed to be loyal to your needs on the fly!

🔍 Easy to start

```csharp
using ConariL l = new("...");
```

🧰 Powerful types

No more manual type conversions and memory management complexities. Because nothing easier than just use it,

[`[⏯]`](https://github.com/3F/Conari/blob/4b17df2a4efd0a5fae4f3498dbe7327db5e43d22/ConariTest/BindingContextTest.cs#L20-L24)
```csharp
using dynamic l = new ConariX("regXwild.dll");

string data = "number = 888;";
bool found = l.replace(ref data, "+??;", "2034;");
// found: true; data: number = 2034;
```

🔨 Its amazing DLR features

```csharp
using dynamic l = new ConariX("...");
l.(curl, 10002, "https://");
```

Still not convinced? Here's full workable code example for [regXwild](https://github.com/3F/regXwild):

```csharp
using var c = ConariL.Make(new("regXwild"), out dynamic l);
// ready for everything even without configuring

using var u = NativeStruct.Make.f("start", "end").Struct;
/* Hey! We just generated a structure like
[StructLayout(LayoutKind.Sequential)]
private struct MatchResult
{
public UIntPtr start;
public UIntPtr end;
}*/

if(l.match("n = '888';", "'*'", 2/*MATCH_RESULT*/, u))
{
/* Now we just generated and invoked this
REGXWILD_API_L bool match
(
const rxwtypes::TCHAR* input,
const rxwtypes::TCHAR* pattern,
rxwtypes::flagcfg_t options,
EssRxW::MatchResult* result
)
*/
dynamic v = u.Access; // just access the EssRxW::MatchResult* result
// v.start == 4; v.end == 9;
}
// Yes, a 4 lines and your task is done; Free memory, Free hands.
```

[`[⏯]`](https://github.com/3F/DllExport/blob/master/src/DllExport/assets/NetfxAsset/Basic.cs) DllExport + Conari

```csharp
[DllExport] // DllExportModifiedClassLibrary.dll
public static IntPtr callme(TCharPtr str, IntPtr structure)
{
if(str != "Hello world!") return IntPtr.Zero;

structure.Native().f("x", "y").build(out dynamic v);
if(v.x > v.y)
{
structure.Access().write(8);
}
return new NativeArray(-1, v.x, 1, v.y);
}
```

[`[⏯]`](https://github.com/3F/DllExport/blob/master/src/DllExport/UnitedTest/NetfxAssetBasicTest.cs)

```csharp
... // host side via C/C++, Java, Rust, Python, ... or even same dotnet C#
using NativeString ns = new("Hello world!");
using NativeStruct nstruct = new(new Arg() { x = 7, y = 5 });

using dynamic l = new ConariX("DllExportModifiedClassLibrary.dll");
IntPtr ptr = l.callme(ns, nstruct);

using NativeArray nr = new(4, ptr); // (nstruct.Data.x == 8) != (nr[1] == 7)
```

🚀 Awesome speed

Optional caching of 0x29 opcodes (Calli) and more.

test of regXwild's algorithms [[340x10000 Unicode](https://github.com/3F/regXwild#speed)] | +icase [x32]| +icase [x64] | `
----------------------------------------------|--------------|-----------------|---
regXwild **native C++** `EXT` algorithm | **~50ms** | **~26ms** | `<<`
regexp-c++11(regex_search) | ~59309ms | ~53334ms |
regexp-c++11(regex_match with endings .*) | ~59503ms | ~53817ms |
.NET Regex engine [Compiled] | ~38310ms | ~37242ms |
.NET Regex engine | ~31565ms | ~30975ms |
regXwild via **Conari** v1.3 (Lambda) - `EXT` | **~54ms** | **~35ms** | `<<`
regXwild via **Conari** v1.3 (DLR) - `EXT` | ~214ms | ~226ms |

🔧 The easiest (most ever) access to any data in unmanaged memory

```csharp
// Everything will be generated at runtime
memory.Native()
.f("Machine", "NumberOfSections") // IMAGE_FILE_HEADER (0xF4)
.align(3)
.t("SizeOfOptionalHeader")
.t("Characteristics")
.region()
.t("Magic") // IMAGE_OPTIONAL_HEADER (0x108)
.build(out dynamic ifh);

if(ifh.SizeOfOptionalHeader == 0xF0) { // IMAGE_OPTIONAL_HEADER64
memory.move(0x6C);
}

// Use it !

ifh.NumberOfSections // 6
ifh.Characteristics // IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE | IMAGE_FILE_DLL
ifh.Machine // IMAGE_FILE_MACHINE_AMD64
ifh.Magic // PE64
```

```csharp
dynamic l = ptr.Native().f("x", "y").build();
l.x // 17
l.y // -23
```

🏄 Most powerful PInvoke and even most convenient use of WinAPI without preparing something

Conari 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()*

```csharp
dynamic user32 = new User32();

user32.ShowWindow(0x000A0A28, 3);
user32.MessageBoxA(0, "Conari in action", "Hello!", 0);
```

```csharp
dynamic kernel32 = new Kernel32();

kernel32.GetModuleHandleA("libcurl-x64");
kernel32.GetModuleHandleW((WCharPtr)ustr);
```

Because our recipe is simple, *Just use it!* and have fun.

🔖 Modern **.NET Core**

Conari 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

🍰 **Open and Free**

Open Source project; MIT License; *Fork! Star! Contribute! Share! Enjoy!*

Conari is available for everyone from 2016 🎉

## [Take a look closer](https://github.com/3F/Conari/wiki/Quick-start)

Conari generally provides two mode,

*Fully automatic* way through its dynamic features (**DLR**). For example, when using the *unmanaged* code:

```csharp
var ptr = d.test(); //lambda ~ bind>("test")();
var codec = d.avcodec_find_encoder(AV_CODEC_ID_MP2); //lambda ~ bind>("avcodec_find_encoder")(AV_CODEC_ID_MP2);
d.push(); //lambda ~ bind("push")();
d.create(ref cid, out data); //lambda ~ bind>("create")(ref cid, out data);
```

This (or like) does not require the any configuration from you, because Conari will do it **automatically**.

*Semi-automatic* way through its custom **lambda expressions**. For example, when using the *unmanaged* code:

```csharp
using(var l = new ConariL("Library.dll"))
{
l.bind>("call")(2, 1);
double num = l.bind>("tonumber")(L, 4);
}
```

This also does not require neither the creation of any additional delegates nor the configuring something. Just a more control through `l.bind<...>("...")` methods that still make you happy;

```csharp
// invoke it immediately
l.bind>("set")(-1, "Hello from Conari !");

// or later
set(-1, "Hello from Conari !");
```

**Native C/C++ structures without declaration** **[[?](https://github.com/3F/Conari/issues/2)]**:

```csharp
// IMAGE_FILE_HEADER: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680313.aspx
dynamic ifh = binaryData.Native()
.t(null, "NumberOfSections")
.align(3)
.t("SizeOfOptionalHeader")
.build();

if(ifh.SizeOfOptionalHeader == 0xF0) { // IMAGE_OPTIONAL_HEADER64
...
}

// IMAGE_DATA_DIRECTORY: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680305.aspx
binaryData.Native()
.t("VirtualAddress")
.t("Size")
.build(out dynamic idd);

DWORD offset = rva2Offset(idd.VirtualAddress);
```

```csharp
IntPtr ptr ...
Raw mt = ptr.Native()
.align(2, "a", "b")
.t("name")
.Raw;

- {byte[0x0000000c]} byte[]
[0] 0x05 byte --
[1] 0x00 byte |
[2] 0x00 byte |
[3] 0x00 byte --^ a = 5
[4] 0x07 byte --
[5] 0x00 byte |
[6] 0x00 byte |
[7] 0x00 byte --^ b = 7
[8] 0x20 byte --
[9] 0x78 byte |_ pointer to allocated string: (CharPtr)name
[10] 0xf0 byte |
[11] 0x56 byte --
...
```

A modern *NativeData* chains for everything (Memory, Streams, Local collections, ...)

```csharp
.move(0x3C, Zone.D)
.read(out LONG e_lfanew)
.move(e_lfanew, Zone.D)
.eq('P', 'E', '\0', '\0')
.ifFalse(_ => throw new PECorruptDataException())
.Native()
.f("Machine", "NumberOfSections")
.align(3)
.t("SizeOfOptionalHeader", "Characteristics")
.region()
.t("Magic") // start IMAGE_OPTIONAL_HEADER offset 0 (0x108)
.build(out dynamic ifh)
.Access
.move(ifh.SizeOfOptionalHeader == 0xF0 ? 0x6C : 0x5C)
.read(out DWORD NumberOfRvaAndSizes)
.Native() // DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
.t("VirtualAddress")
.t("Size")
.build(out dynamic idd)
.Access.move(8 * (NumberOfRvaAndSizes - 1))
...

// ifh.Machine; - IMAGE_FILE_MACHINE_AMD64
// e_lfanew - 0x110
// NumberOfRvaAndSizes - 16
// idd.VirtualAddress - VA 0x7070
// ifh.Characteristics; - IMAGE_FILE_EXECUTABLE_IMAGE
// | IMAGE_FILE_LARGE_ADDRESS_AWARE
// | IMAGE_FILE_DLL
// ifh.Magic; - PE64
// ifh.NumberOfSections; - 6
// ...
```

**Calling Convention** & **Name-Decoration** **[[?](https://github.com/3F/Conari/issues/3)]**

```csharp
using(var l = new ConariL("Library.dll", CallingConvention.StdCall))
{
//...
l.Mangling = true; // _get_SevenStdCall@0 <-> get_SevenStdCall
l.Convention = CallingConvention.Cdecl;
}
```

**Exported Variables** [[?](https://github.com/3F/Conari/issues/7#issuecomment-269123650)] & **raw accessing** [[?](https://github.com/3F/Conari/issues/17#issuecomment-716176288)]

```csharp
l._.ADDR_SPEC // DLR, 0x00001CE8
l.V.get("ADDR_SPEC"); // lambda, 0x00001CE8
std_cin = l.addr("?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A");
```

**Aliases [[?](https://github.com/3F/Conari/issues/9#issuecomment-273855381)]**

```csharp
// v1.3+
l.Aliases["Flag"] = l.Aliases["getFlag"] = l.Aliases["xFunc"]; //Flag() -> getFlag() -> xFunc()->...
// ...
l._.getFlag();
```

**Additional types**

* TCharPtr, CharPtr, WCharPtr, float_t, int_t, ptrdiff_t, size_t, uint_t, ...
* NativeString\ (+NativeStringManager\) - Fully supports TCharPtr, CharPtr, WCharPtr;
* NativeStruct - Fully automatic way of working with structures without declarations using NativeData chains;
* NativeStruct\ - Semi-automatic way of working with structures using CLR types declarations;
* NativeArray\
* ._T("...") - NativeString\ via NativeStringManager\
* ...

```csharp
using var a = new NativeString("Hello");
using var b = a + " world!"; // unmanaged C-string, a Unicode characters
```

```csharp
CharPtr name = c.to(1, out size_t len);
//CharPtr name = c.bind>("to")(1, out size_t len);
string myName += name; // 8 bit C-string and managed string (UTF-16)
```

```csharp
using NativeArray nr = new(pointer); // points to ~0x2674F89EDF0
nr[0] = 1; nr[1] = 2;
```
```csharp
using NativeArray nr = new(1, 2, 3);
nr[0] = -1;
nr[1] = 0;
nr[2] = 1;

Assert.True(nr == new int[] { -1, 0, 1 });
```

```csharp
using var u = new NativeStruct();
l.match(
"[system]", "Sys###",
EngineOptions.F_ICASE | EngineOptions.F_MATCH_RESULT,
u
);
u.Data.start // 1
u.Data.end // 7
```

```csharp
using ConariL l = new("regXwild.dll");
l._.replace
(
l._T("number = 888;", out CharPtr result),
l._T("+??;"), l._T("2034;")
);
// result: number = 2034;
```

```csharp
using dynamic l = new ConariX(RXW_X);

bool found = l.replace
(
"Hello {p}".Do(out TCharPtr result),
"{p}",
"world!"
); // found: true; result: Hello world!
```

and more ...

### [✏ Examples](https://github.com/3F/Conari/wiki/Examples)

How about [regXwild](https://github.com/3F/regXwild) (⏱ Superfast ^Advanced wildcards++? on native unmanaged C++) in your C# code?

```csharp
using dynamic l = new ConariX("regXwild.dll");
if(l.match(input, "'+.#?'")) {
// ... '1.4', '1.04', ...
}
```
Yes, you don't need to do anything else! Conari will prepare everything for binding with the following native method instead of you:

```cpp
REGXWILD_API_L bool match
(
const rxwtypes::TCHAR* input,
const rxwtypes::TCHAR* pattern,
rxwtypes::flagcfg_t options = 0,
EssRxW::MatchResult* result = nullptr
);
```