Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Unknown6656 opened this issue Jun 4, 2016 · 10 comments
Closed

Comments

@Unknown6656
Copy link

Unknown6656 commented Jun 4, 2016

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

@HaloFour
Copy link

HaloFour commented Jun 4, 2016

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;
}

@Unknown6656
Copy link
Author

@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,

@tomrus88
Copy link

tomrus88 commented Jun 5, 2016

Similar feature request already exists: #1013. And yes, would be nice to have such feature.

@Unknown6656
Copy link
Author

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

@mwwhited
Copy link

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

@OmegaExtern
Copy link

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

@Unknown6656
Copy link
Author

@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

@securityvoid
Copy link

FYI, #1013 is also a duplicate of this.

I'd love to see this.

@Unknown6656
Copy link
Author

Unknown6656 commented Nov 18, 2016

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

@Unknown6656 Unknown6656 changed the title [Proposal] Allow C# to export functions to native code [Proposal] Allow C# to export functions (and constants) to native code Nov 18, 2016
@gafter
Copy link
Member

gafter commented Mar 22, 2017

Moved to dotnet/csharplang#308

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants