0

I have a Structure with a nested Structure. Now I need to pass this Structure to a C-Dll. But if I call Marshal.SizeOf(Person) I get an Exception which says that no meaningful size or offset can be compute.

Example:

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Structure Person
<MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef:=GetType(OrganMarshaler))>
Public Organs as Organs
public Name as String
Public FirstName as String
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Structure Organs
Public Heart As Boolean
Public Stomach as Boolean
end Structure

Imports System.Runtime.InteropServices

Public Class OrganMarshaler
    Implements ICustomMarshaler

    Private _managedObjects As New Dictionary(Of IntPtr, Object)

    ' Singleton instance of the custom marshaler
    Private Shared _instance As VBLObjectHeaderBaseMarshaler

    Private Shared Function GetInstance(cookie As String) As OrganMarshaler
        If _instance Is Nothing Then
            _instance = New OrganMarshaler()
        End If
        Return _instance
    End Function

    Public Sub CleanUpManagedData(managedObj As Object) Implements ICustomMarshaler.CleanUpManagedData
        'Nothing to do 
    End Sub

    Public Sub CleanUpNativeData(pNativeData As IntPtr) Implements ICustomMarshaler.CleanUpNativeData
        Marshal.FreeCoTaskMem(pNativeData)
        pNativeData = IntPtr.Zero
    End Sub

    Public Function GetNativeDataSize() As Integer Implements ICustomMarshaler.GetNativeDataSize
        Return Marshal.SizeOf(GetType(Organs))
    End Function

    ''' <summary>
    ''' Marshal the managed object to native format and return the native pointer
    ''' </summary>
    ''' <param name="managedObj"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function MarshalManagedToNative(managedObj As Object) As IntPtr Implements ICustomMarshaler.MarshalManagedToNative
        If managedObj Is Nothing Then
            Return IntPtr.Zero
        End If
        If TypeOf managedObj Is Organs = False Then
            Throw New ArgumentException("The input argument is not Organs.")
        End If

        Dim ptr As IntPtr = Marshal.AllocCoTaskMem(GetNativeDataSize)
        Marshal.StructureToPtr(managedObj, ptr, False)

        SyncLock _managedObjects
            _managedObjects.Add(ptr, managedObj)
        End SyncLock

        Return ptr
    End Function

    Public Function MarshalNativeToManaged(pNativeData As IntPtr) As Object Implements ICustomMarshaler.MarshalNativeToManaged
        SyncLock _managedObjects
            Dim headerBase As Organs = CType(_managedObjects(pNativeData), Organs)
            _managedObjects.Remove(pNativeData)
            Marshal.PtrToStructure(Of Organs)(pNativeData, headerBase)
            Return headerBase
        End SyncLock

    End Function

End Class

I do not know how to debug this Marshaler Class. I can set Breakpoints, but I never reach them.

Try to use a Custom Marshaler Class (implement ICustomMarshaler)

0 Answers0