Click here to Skip to main content
15,946,988 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,
I am writing a .net wrapper for a C library. My problem is marshalling of non-blittable types.

The library uses structures with nested structures.
The C function requires a pointer as a parameter.

VB
<DllImport(log.dll, CharSet:=CharSet.Ansi, EntryPoint:="Write", CallingConvention:=CallingConvention.StdCall)>
    Private Shared Function Write(fooPtr As IntPtr) As Int32
    End Function

<StructLayout(LayoutKind.Sequential, Pack:=1)>
Public Structure Foo
    Public AdditionalInformations As AdditionalInformations'Nested Structure
   
    Public Tick As Integer
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Public Trick As Integer()
    Public Trick As Integer
    Public Truck As Integer

    <MarshalAs(UnmanagedType.LPStr)>
    Public Description As String ' name in MBCS
    Public Data As Byte() ' data as array with variable length
End Structure

<StructLayout(LayoutKind.Sequential, Pack:=1)>
   public Structure AdditionalInformations
   public Informations as Informations  'Nested Structure
   public Bar as integer
End Structure


<StructLayout(LayoutKind.Sequential, Pack:=1)>
public Structure Informations 
   public Size as Integer
   public Name as Integer
End Structure


If I try to pin the Memory of this Structure using GCHandle.Alloc(Foo, GCHandleType.Pinned) I got an Exception Object doesn't contains primitive data types.

Is it possible to use the MarshalAs-Attributes to tell the Compiler how this Structures should be interpreted ?

What I have tried:

Tried to use MarshalAs Attributes and Marshal.StructureToIntptr (allocate size of structure and call Marshal.StructureToPtr).

Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Foo))
     Marshal.StructureToPtr(Foo, pnt, False)
Posted
Updated 12-Jun-23 6:42am
v3
Comments

1 solution

Well, you need to create an instance of class, as is described here: Marshalling Classes, Structures, and Unions - .NET Framework | Microsoft Learn[^]

C#
MyPerson personName;
        personName.first = "Mark";
        personName.last = "Lee";

        IntPtr buffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(personName));
        Marshal.StructureToPtr(personName, buffer, false);


So, instead of:
VB.NET
Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Foo))
     Marshal.StructureToPtr(Foo, pnt, False)

You need something like that:
Dim f as Foo = ...
Dim pnt As IntPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(f))
     Marshal.StructureToPtr(f, pnt, False)


Do you see the difference?
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900