Runtime: PInvoke function that returns a struct

Created on 26 Aug 2018  路  9Comments  路  Source: dotnet/runtime

One of my customers encountered a problem today that doesn't appear with .NET Framework/Mono.

For some reason in this function (ENet.cs line 747):

[DllImport(nativeLibrary, CallingConvention = CallingConvention.Cdecl)]
internal static extern Address enet_peer_get_address(IntPtr peer);

marshaling is not possible of an ENetAddress struct (ENet.cs line 64) which internally contained in Address (ENet.cs line 90):

[StructLayout(LayoutKind.Sequential)]
public struct ENetAddress {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] host;
    public ushort port;
}

look at Peer.Address (ENet.cs line 515).

The runtime throws this exception:

Unhandled Exception: System.Runtime.InteropServices.MarshalDirectiveException: Method's type signature is not PInvoke compatible.
at ENet.Native.enet_peer_get_address(IntPtr peer)
at ENet.Peer.get_Address() in E:TestENetServerENet.cs:line 517
at TestENetServer.Program.Main(String[] args) in E:TestENetServerProgram.cs:line 25

Here's an example of projects - ENetCSharpTest.zip
Simple run the server and then the client, and you will catch an exception.

Here's repository with a complete source code including the native library - https://github.com/nxrighthere/ENet-CSharp

area-Interop-coreclr

Most helpful comment

Fixed by dotnet/coreclr#21470

All 9 comments

cc @luqunl

As a workaround, I changed the functions to obtain an address directly from the unmanaged side, instead of marshaling a struct.

cc @AaronRobinsonMSFT (wrt marshalling test coverage)

@jkoritzinsky Didn't you add some testing for this scenario?

I thought I did. I'll go check.

Fixed by dotnet/coreclr#21470

Sorry for the late reply: I just add as an information for other people stumbling in similar cases that the change in dotnet/coreclr#21470 is only available in recent .NET core runtimes (unfortunately the improvement has not been backported in .NET framework so far) and it also allows marshaling of structures like the following as return values:

[StructLayout(LayoutKind.Sequential)]
struct PString
{
    [MarshalAs(UnmanagedType.LPWStr, SizeParamIndex = 1)]
    public string String;
    public int Lenght;
}

unfortunately the improvement has not been backported in .NET framework so far

I want to set expectations here with respect to the above. There are no plans (now or in the future) to port any new interop work to .NET Framework.

I want to set expectations here with respect to the above. There are no plans (now
or in the future) to port any new interop work to .NET Framework.

Perfectly understandable to me. Thank you very much for the clarification.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nalywa picture nalywa  路  3Comments

GitAntoinee picture GitAntoinee  路  3Comments

v0l picture v0l  路  3Comments

aggieben picture aggieben  路  3Comments

jamesqo picture jamesqo  路  3Comments