tags:

views:

76

answers:

2

From my managed code (let's call it MyLib) I am using a library (let's call it OtherLib) that is basically a wrapper around some c++ code (I have never seen the wrapper code or have had access to its source, nor will I have it).

When my calling library is targetting the 3.5 framework all is good and dandy. When I make it target .NET 4.0 I am getting this exception when using a method from OtherLib:

Cannot marshal 'parameter #3': Invalid managed/unmanaged type combination (this value type must be paired with Struct).

This happens, when I am calling a method on one of the types supplied by the wrapper. On line 4 I get above stated exception.

            If results.Compute(coordOrg, True, Nothing) Then
                 For Each Coord As Coordinate3D In queueDest
                    resDM(fromIndex, Coord.zMeter, DistanceCostType.CrowFly) = Math.Round(Math.Sqrt(Math.Pow(pointFrom.X - Coord.xMeterOrLongDeg, 2) + Math.Pow(pointFrom.Y - Coord.yMeterOrLatDeg, 2)) / 1000, 6)
                    resDM(fromIndex, Coord.zMeter, DistanceCostType.Road) = Math.Round(results.GetCost(Coord, m_itiDistance) / 100000, 6)
                    resDM(fromIndex, Coord.zMeter, DistanceCostType.Time) = Math.Round(results.GetCost(Coord, m_itiTime) / 100 / 60, 4)
                Next
            End If

Has anyone encountered something similar ?

EDIT: I have tried switching the targetting from 3.5 to 4.0 and back again. Under 3.5 all work fine under 4.0 it throws this exception. I have tried creating a wrapper project targetting 3.5, exposing a static class retrieving results from the OtherLib. Again when I call it from project compiled to 4.0 it fails and works when compiled for 3.5

EDIT2: Enum definition

Public Enum DistanceCostType
    CrowFly
    Road
    Time
End Enum
A: 

:) It seems there aren’t many people who’ve run into this specific problem, but I’m one of them! My OpenCL bindings have this issue, and I don’t know to resolve it. Did anyone manage to get a fix or further information on this issue?

Here are the P/Invoke definitions (the last parameter is the problem). There is also a detailed discussion with a way to reproduce the problem in the "Discussions" tab at openclnet.codeplex.com (under "New test for you").

Cl.Event is a structure with a single IntPtr member.

http://openclnet.codeplex.com/SourceControl/changeset/view/77409#1251581 (look for "struct Event").

  1. The one below works for .NET 4.0 but not for version below it with the error (Cannot marshal 'parameter #9': Invalid managed/unmanaged type combination (Int/UInt must be paired with SysInt or SysUInt))

    [DllImport(Library)]
    private static extern ErrorCode clEnqueueWriteBuffer(IntPtr commandQueue,
                                                         IntPtr buffer,
                                                         Bool blockingWrite,
                                                         IntPtr offset,
                                                         IntPtr cb,
                                                         IntPtr ptr,
                                                         uint numEventsInWaitList,
                                                         [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
                                                         [Out] [MarshalAs(UnmanagedType.Struct)] out Event e);
    
  2. This one works on .NET 3.5 and below, but fails on .NET 4.0 with the error (Cannot marshal 'parameter #9': Invalid managed/unmanaged type combination (Int/UInt must be paired with Struct))

    [DllImport(Library)]
    private static extern ErrorCode clEnqueueWriteBuffer(IntPtr commandQueue,
                                                         IntPtr buffer,
                                                         Bool blockingWrite,
                                                         IntPtr offset,
                                                         IntPtr cb,
                                                         IntPtr ptr,
                                                         uint numEventsInWaitList,
                                                         [In] [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.SysUInt, SizeParamIndex = 6)] Event[] eventWaitList,
                                                         [Out] [MarshalAs(UnmanagedType.SysUInt)] out Event e);
    
Ananth
Well I still don't know the answer by any chance. I worked around it in a different way.
Tomas Pajonk
A: 

Until Framework 4, it was somewhat an oddity that structs containing only one field of type IntPtr or int couldn't be marshaled as Struct.

Louis.fr