Roslyn: [Proposal] Allow C# to export functions (and constants) to native code

Created on 4 Jun 2016  路  10Comments  路  Source: dotnet/roslyn

_(The title nearly says it all)_
I would like to propose the ability to export a function written in a C#-project to native code (C++ etc.) -- quasi the opposite of a P/Invoke-call.

As the CLR has this already implemented (See Serge Lindin's book about the .NET 2.0 Assembler, chapter 18, pages 380 and following) since v2.0, no CLR changes have to be made for this feature.

An "exported" function must be marked as static and should be non-private. A possible example could be:

public static export int Add(int a, int b)
{
    return a + b;
}

which would compile into something like this:

.corflags 0x00000002
.vtfixup [1] int32 fromunmanaged at VT_01
.data VT_01 = int32(0)
...
.method public static int32 Add(int32 a, int32 b) // notice the lack of the 'cil managed' keyword
{
    .vtentry 1:1
    .export [1]
    .maxstack 2
    ldarg.0
    ldarg.1
    add
    ret
}

which could be called from other (native) asseblies.
If one would like to export the function under a different name (e.g. as MyAdd instead of Add), it could be done as follows:

public static export "MyAdd" int Add(int a, int b) { ... }

Which would result in the following CIL-code:

.corflags 0x00000002
.vtfixup [1] int32 fromunmanaged at VT_01
.data VT_01 = int32(0)
...
.method public static int32 Add(int32 a, int32 b) // notice the lack of the 'cil managed' keyword
{
    .vtentry 1:1
    .export [1] as MyAdd
    ...
}

Of course, all parameters and return values must be value types (native arrays, primitives, native structures or pointer).

For exporting constants, see this post


I know, that the the project Unmanaged Exports by Robert Giesecke exists, however I would like to see this feature implemented into the C#-language without the need of external references or extensions.

1 - Planning Area-Language Design Feature Request

Most helpful comment

Personally, I think that rather than a new keyword that I'd rather see another pseudo-attribute, DllExportAttribute:

[DllExport(ExportAs = "MyAdd")]
public static int Add(int x, int y) {
    return x + y;
}

All 10 comments

Personally, I think that rather than a new keyword that I'd rather see another pseudo-attribute, DllExportAttribute:

[DllExport(ExportAs = "MyAdd")]
public static int Add(int x, int y) {
    return x + y;
}

@HaloFour: Yes, you are probably right with an (pseudo-)attribute usage to keep consistency with the DllImport-Attribute.

Come to think of it, it would be easier to port code, which used the Unmanaged Exports-project previously, as the syntax would remain the same,

Similar feature request already exists: https://github.com/dotnet/roslyn/issues/1013. And yes, would be nice to have such feature.

@tomrus88: Thank you very much Sir for mentioning it... I will look into the linked reference

Attributes like this are why I was hoping Roslyn would have given us a compiler pipeline. Injecting extra extensions in such a case would be childs play

(See Serge Lindin's book about the .NET 2.0 Assembler, chapter 18, pages 380 and following) since v2.0

Quote from page 386:

The good news is that version 2.0 of the IL assembler does not require these directives at
all, as long as the v-table and VTFixup table are used for unmanaged exports only. Just specify
the .export directives in the methods you want to export to the unmanaged world, and the
flags, the v-table, and its fixups will be generated automatically by the compiler, with the slot
size adjusted for the target platform

Well, just .export directive must be injected/inserted and that's it (assuming a program has to be built for either x64 or x86 target processor). Additionally, modopt could be injected/inserted to set specific calling convention (when it is marshaled as unmanaged):

.method public static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) Foo()
{
    .export [1] as Bar // Export #1, Name="Bar"
    // ...
}

That's all I have wanted to point out here. I hope one day C#/VB will have this.

@OmegaExtern : I always use the IL Support extension for VS, but that is a bit tedious. I also hope that VB/C#/F#/J#/ ..... will have this feature

FYI, https://github.com/dotnet/roslyn/issues/1013 is also a duplicate of this.

I'd love to see this.

There is something, which I have forgotten to mention while creating this issue:
What about exporting constants?

In C++, you can do something like this:

extern "C" __declspec(dllexport) static DWORD MyConstant = 0x00000042;

Is this possible to do in C#?
It could be written as

[DllExport]
public const int MyConstant = 0x00000042;

I think the required CIL code is something along these lines:

.field public static int32 MyConstant at data_01
...
.data data_01 = int32(0x00000042)

This could help me a lot by writing

[DllExport]
public const int NvOptimusEnablement = 1;

instead of

.data data_01 = int32(1)

.class public auto ansi '<Module>'
{
    .field public static int32 NvOptimusEnablement at data_01
}

every time I need NVidia-Optimus-support for my .NET executable

Was this page helpful?
0 / 5 - 0 ratings

Related issues

codingonHP picture codingonHP  路  3Comments

nlwolf picture nlwolf  路  3Comments

marler8997 picture marler8997  路  3Comments

vbcodec picture vbcodec  路  3Comments

DavidArno picture DavidArno  路  3Comments