Skip to content
Denis Kuzmin (github/3F) edited this page Mar 6, 2025 · 14 revisions

Configure projects in seconds through DllExport manager.

Set it up like:

  1. Get this (~28 Kbytes) into solution folder. Then [Click it] (or command this)
  2. Select preferred projects to install and configure what you need.
  3. (optional) Define external storage to get more automation.
  4. Click [Apply].

Now you're ready to export.

Still not sure? See Various cases in a few steps (Screencast) πŸ“Ή

.NET Core

.NET DllExport is ready for πŸ—Ž .Net Core projects starting with 1.7

To start export

To export something just add [DllExport] attribute for any static methods your want to export. You can also override the calling convention and specify a custom function name if you need.

⚠ // Cdecl is the default calling convention for .NET DllExport

πŸ§ͺ Play with demo project (native C++). More examples are waiting for you here

C#

[DllExport]
public static void hello() { /* ... */ }
[DllExport]
public static int apply(IntPtr ptr) => 0;
[DllExport("Init", CallingConvention.StdCall)]
[DllExport(CallingConvention.StdCall)]
[DllExport("MyFunc")] // Cdecl

F#

[<DllExport>]
static member hello() = printfn ".NET DllExport"
[<DllExport>]
static member apply(ptr: nativeint): int = 0
[<DllExport("Init", CallingConvention.StdCall)>]
[<DllExport(CallingConvention.StdCall)>]
[<DllExport("MyFunc")>] // Cdecl

Merge or provide FSharp.Core module

VB.NET

<DllExport>
Public Shared Sub hello()
    ' ...
End Sub
<DllExport>
Public Shared Function apply(ByVal ptr As IntPtr) As Integer
    Return 0
End Function
<DllExport("Init", CallingConvention.StdCall)>
<DllExport(CallingConvention.StdCall)>
<DllExport("MyFunc")> ' Cdecl

Namespaces

You can configure our tool for any related namespaces in your projects for some additional purpose or just for your convenience in your work.

It's safe because the final modified .NET module (.dll or .exe) will not contain any links with our libraries.

About data types

Only primitive/scalar types since this operates under P/Invoke. In any case it will be used through internal marshaling, but non-scalar types may require additional handling as for managed strings.

About default marshaling behavior you can read here: https://docs.microsoft.com/en-us/dotnet/framework/interop/default-marshaling-behavior

You can also try to manually use MarshalAs attribute.

However, scalar types in arguments/return value are a more powerful way to control anything. And this is enough to work with any types like a pointer to allocated data. Means ~ IntPtr instead of String etc.

Here you can also find how to use any complex types like structures, or strings: https://www.youtube.com/watch?v=QXMj9-8XJnY (wiki: πŸ—Ž Complex types and Strings).

Conari

.NET DllExport relies partly on Conari which helps to work with any data from unmanaged memory (including native or binary data from the heap) and even accessing to complex types like structures without their declaration at all.

But Conari can also help for both cases when you have managed and unmanaged host side to communicate between.

For example,

[⏯]

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

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

[⏯]

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

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

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

In [Pre-processing] tab you can optionally integrate Conari inside your final modules (no extra .dlls etc): https://github.com/3F/DllExport/wiki/PreProc#conari-support

πŸ—Ž

πŸ—”

πŸ“‚

Clone this wiki locally