Skip to content
Niggggggo edited this page May 29, 2020 · 4 revisions

Managed & Unmanaged PInvoke. C++ ❤ C#

(Screencast) Managed & Unmanaged; PInvoke. C++ ❤ C# /Part-1

  • 00:06 - Declaring something from managed C# into unmanaged env ((host side)) like for native C++ below.

  • 01:31 - By the way, Checking the exports from C# dll via available pe-viewer.

  • 02:20 - To use managed code directly in our native unmanaged C++.

  • 03:48 - By the way, we can also try to understand where each function can be found after loading module into memory by its address (RVA) from pe-records about ... IMAGE_EXPORT_DIRECTORY.

  • 05:19 - Declaring something from unmanaged C++ for using inside managed C# ((host side)) below. By the way:

    • we'll use C-mangling just for convenience at least for this examples.
    • we still use exe module, just for fun, but do not forget about init CRT for other code.
  • 06:14 - By the way, we'll use Conari for binding any native or binary data. Which also used in [ Part-2 ] for examples with complex types (like structures) or strings.

  • 08:19 - Something ... two from unmanaged C++. But now there used a native dll module instead of exe.

  • @ 02:24 Means a two things:

    1. Types are not identical. PInvoke-mechanism mainly operates with the sizes for the data, not its types.
    2. A call at the received address can be with any similar signature (compatible with required arguments and optionally return value).

    That is, the ~call-mechanism is flexible enough to avoid some specifications.

    For more information, please use MSDN and other related documentation.
    But you can also use my old an examples and explanations, for example:

Raw Source code from Screencast

First way

C++

typedef int(__cdecl *_add)(int a, int b);
typedef bool(__cdecl *saySomething)();

HMODULE lib = LoadLibrary("csharp.dll");
auto pAdd = (_add)GetProcAddress(lib, "_add");
int c = pAdd(5, 7);

auto pSaySomething = (saySomething)GetProcAddress(lib, "saySomething");
bool dlgres = pSaySomething();

C#

[DllExport]
public static int _add(int a, int b)
{
    return a + b;
}

[DllExport]
public static bool saySomething()
{
    DialogResult dlgres = MessageBox.Show(
        "Hello from managed environment !",
        ".NET clr",
        MessageBoxButtons.OKCancel
    );

    return dlgres == DialogResult.OK;
}

Second way

C++

extern "C" __declspec(dllexport) int cadd(int a, int b)
{
    return a + b;
}

EXAPI void something()
{
    MessageBox(
        NULL,
        _T("Hello from unmanaged env !"),
        _T("C++"),
        MB_ICONINFORMATION | MB_OK
    );
}

C#

using(var l = new ConariL(@"D:\Samples\PENative\x64\Debug\PENative.exe")) {
    int c = l.DLR.cadd<int>(7, 5);

    using(var l2 = new ConariL(@"D:\Samples\PENative\x64\Debug\DllNative.dll")) {
        l2.DLR.something();
    }
}

References