AaronRobinsonMSFT / DNNE

Prototype native exports for a .NET Assembly.
MIT License
406 stars 41 forks source link

added additional wide string support for marshalling wide strings #122

Closed mwetzko closed 2 years ago

mwetzko commented 2 years ago

added char* (C#) support for export (gen tool) improved some code added string-testing unit tests some code has been formatted due to auto format

mwetzko commented 2 years ago

I reverted the boolean commit

AaronRobinsonMSFT commented 2 years ago

Thank you much! Do you need package published soon?

mwetzko commented 2 years ago

No hurry. I was looking for the boolean part to be in there. Please let me know what would be an acceptable boolean support, because at some point you will need to specify how booleans are coming in and out. Because if you do not control the part of the caller, you have to code UnmanagedType.U1 or UnmanagedType.Bool as boolean marshalling.

If I find a solution that would allow such a statement:

[UnmanagedCallersOnly]
// return bool defaults to C99 'bool'
public static bool Something(){}

[UnmanagedCallersOnly]
[return: MarshalAs(UnmanagedType.Bool)] // use Win32 'BOOL'
public static bool Something(){}

Would that be ok with you?

AaronRobinsonMSFT commented 2 years ago

Because if you do not control the part of the caller, you have to code UnmanagedType.U1 or UnmanagedType.Bool as boolean marshalling.

One of the main principals of DNNE is ensure there is no marshalling involved at all. This means we are simply exposing types to the C environment and as such we are required to follow what C guarantees. In this case, the size of C-bool is implementation defined. I believe since C99, even true and false are typed as ints.

This doesn't mean there is no hope, but it does mean we need to understand what guarantees we can rely on. Since bool in C# is defined to be 1 byte and uint8_t is also defined to be 1 byte, I could see an argument for the generated C export producing a uint8_t when it encounters a C# bool. However, I don't see how we could use C99's definition given it is implementation dependent.

mwetzko commented 2 years ago

I understand you to keep things as small and understandable as possible for people. But I also noticed that I'm not the only one who would like to have that boolean support. When I search the net, I can only find the C99 _Bool type which has the size of 1 byte (char size). With the <stdbool.h> header, it's now 'bool' also 1 byte. So if you ask me (not considering the VARIANT BOOL) we only have to deal with the 1 byte bool and the 4 byte BOOL.

And because we only use the "MarshalAs" to let your gen tool know what byte conversation we would like (either U1 or Bool, defaults to U1) we don't do marshalling really, just using either uint8_t or int32_t as the type for the generated C file.

Anyway, thanks for the awesome project! I guess I will use int for my BOOL conversation.