Interop Error: Causes generic TypeLoad error...

  • Thread starter Thread starter Robert Bouillon
  • Start date Start date
R

Robert Bouillon

I'm creating a managed wrapper for printing, and I defined a struct to
marshal some data. Because of .NET interop limitations on .NET CF, I
defined the struct as LayoutKind.Explicit. The CLR threw a "Could not
load type" on the implementing class when I declared the a variable for
the struct. Changing the StructLayout to LayoutKind.Sequential fixed
the problem, but I may not always be able to fix the problem that way.
What was I doing wrong? Is this a CLR bug? ILDASM showed the DLL did
indeed have the class, so it's not a compiler issue....

public class MyClass
{
//Commenting out this line stops the error...
private DocumentInformation _info;

{...}

//Changind this to LayoutKind.Sequential also stops the error...
[StructLayout(LayoutKind.Explicit)]
private struct DocumentInformation {
[FieldOffset(0)]
public short cbSize;
[FieldOffset(2)]
public IntPtr lpszDocName;
[FieldOffset(6)]
public IntPtr lpszOutput;
[FieldOffset(10)]
public IntPtr lpszDatatype;
[FieldOffset(14)]
public uint fwType;
}
 
I'm not a big expert on marshaling and interop, but that layout is wrong, if
you're passing it to unmanaged code. You've got 4-byte values *not* on
4-byte boundries, which will cause alignment exceptions on most CE
processors...

Paul T.
 
Paul,

Thanks for the reply. Not sure how I missed that....

A more descriptive exception from the runtime would have been nice.

The code works now. Thanks!

--ROBERT
 
I'm having a similar problem (I'm trying to make an overlay field here
though) -- getting TypeLoadException on the following:

<StructLayout(LayoutKind.Explicit)> _
Public Class KernelDeviceID ' from uniqueid.h
<FieldOffset(0)> Public Size As Integer
<FieldOffset(4)> Public PresetIDOffset As Integer
<FieldOffset(8)> Public PresetIDSize As Integer
<FieldOffset(12)> Public PlatformIDOffset As Integer
<FieldOffset(16)> Public PlatformIDSize As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
<FieldOffset(0)> Public Struct() As Byte

Is this impossible to do in NETcf?

I also tried this (in case the first set of fields has to cover the whole
structure size):

<StructLayout(LayoutKind.Explicit)> _
Public Class KernelDeviceID ' from uniqueid.h
<FieldOffset(0)> Public Size As Integer
<FieldOffset(4)> Public PresetIDOffset As Integer
<FieldOffset(8)> Public PresetIDSize As Integer
<FieldOffset(12)> Public PlatformIDOffset As Integer
<FieldOffset(16)> Public PlatformIDSize As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=236)> _
<FieldOffset(20)> Public IDbytes() As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
<FieldOffset(0)> Public Struct() As Byte

Any idea?

Thanks for any help,
Steve
 
The marshaler won't handle these. Pass them as pure byte arrays and extract
the members manually.

-Chris
 
Thanks for the reply, Chris.

My idea was to load the byte array (Public Struct() As Byte) -- use Struct
as the variable in my P/Invoke call of KernelIOControl, and then the overlay
would automatically load the integers. Ah, well.

Steve
 
Yeah, would be nice if it allowed that. I'd personally love it if we could
just memcpy the return into the address of a managed struct - unfortunately
I've found no simple way to achieve it (and believe me, I've tried).

-Chris
 
Back
Top