Interop Error: Causes generic TypeLoad error...

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;
}
 
P

Paul G. Tobey [eMVP]

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.
 
R

Robert Bouillon

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
 
G

Guest

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
 
G

Guest

The marshaler won't handle these. Pass them as pure byte arrays and extract
the members manually.

-Chris
 
G

Guest

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
 
G

Guest

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top