views:

494

answers:

2

I want to call Garmin API (http://developer.garmin.com/mobile/mobile-sdk/) in VB.Net Compact Framework project. The API is in C++, so i´m making a C# dll project as intermediate way between API dll and VB.Net. I have some problems while executing my code because it throw a NotSupportedException (bad arguments type, i think) in QueCreatePoint call. Here is the C++ API code, and my C# work:

-- C++ Functions prototype and C# P/Invoke Calls ----------

QueAPIExport QueErrT16 QueCreatePoint( const QuePointType* point, QuePointHandle* handle );

QueAPIExport QueErrT16 QueClosePoint( QuePointHandle point );

[DllImport("QueAPI.dll")] private static extern QueErrT16 QueCreatePoint(ref QuePointType point, ref uint handle);

[DllImport("QueAPI.dll")] private static extern QueErrT16 QueRouteToPoint(uint point);

-- QueErrT16 ----------

typedef uint16 QueErrT16; enum { ... }

public enum QueErrT16 : ushort { ... }

-- QuePointType ----------

typedef struct { char id[25]; QueSymbolT16 smbl; QuePositionDataType posn; } QuePointType;

public struct QuePointType { public string id; public QueSymbolT16 smbl; public QuePositionDataType posn; }

-- QueSymbolT16 ----------

typedef uint16 QueSymbolT16; enum { ... }

public enum QueSymbolT16 : ushort { ... }

-- QuePositionDataType ----------

typedef struct { sint32 lat; sint32 lon; float altMSL; } QuePositionDataType;

public struct QuePositionDataType { public int lat; public int lon; public float altMSL; }

-- QuePointHandle ----------

typedef uint32 QuePointHandle;

In C# i manage it as uint var.

-- And this is my current C# function to call all this ----------

public static QueErrT16 GarminNavigateToCoordinates(double latitude , double longitude)
{
    QueErrT16 err = new QueErrT16();

    // Open API
    err = QueAPIOpen();
    if(err != QueErrT16.queErrNone) 
    {
        return err;
    }

    // Create position
    QuePositionDataType position = new QuePositionDataType();
    position.lat = GradosDecimalesASemicirculos(latitude);
    position.lon = GradosDecimalesASemicirculos(longitude);

    // Create point
    QuePointType point = new QuePointType();
    point.posn = position;

    // Crete point handle
    uint hPoint = new uint();

    err = QueCreatePoint(ref point, ref hPoint);  // HERE i got a NotSupportedException
    if (err == QueErrT16.queErrNone) 
    {
        err = QueRouteToPoint(hPoint);
    }

    // Close API
    QueAPIClose();

    return err; 
}

I will appreciate any help. Thanks.

A: 

you could always create a CPP/CLI project that will wrap the native API with a managed API. Usually it's much simpler to write a managed wrapper this way instead of using DllImprt.

Wow, it looks hard. There are any tool to make the wrapper? My knowledge of C is low, and have no idea about wrapping a native API.I see that other person make a Wrapper (http://christian-helle.blogspot.com/2008/02/integrating-with-garmin-mobile-xt.html), but i can´t use it in .NET 1.1. This is the reason i use P/Invoke instead.Thanks.
A: 

You should be able to use pInvoke on these directly from VB without the C# wrapper (or the C++ wrapper). The declarations should be something along these lines:

'QueAPIExport QueErrT16 QueCreatePoint( const QuePointType* point, QuePointHandle* handle );'

'QueAPIExport QueErrT16 QueClosePoint( QuePointHandle point );'

<DllImport("QueAPI.dll")> _
Private Shared Function QueCreatePoint(ByRef point As QuePointType, ByRef handle As Integer) As QueErrT16
End Function

<DllImport("QueAPI.dll")> _
Private Shared Function QueRouteToPoint(ByVal point As Integer) As QueErrT16
End Function


'-- QueErrT16 ----------'

'typedef uint16 QueErrT16; enum { ... }'

Public Enum QueErrT16 As Short
    blah
End Enum


'-- QuePointType ----------'

'typedef struct { char id[25]; QueSymbolT16 smbl; QuePositionDataType posn; } QuePointType;'

'Remeber to initialize the id array.'
Public Structure QuePointType
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=25)> Public id As Byte()
    Public smbl As QueSymbolT16
    Public posn As QuePositionDataType
End Structure


'-- QueSymbolT16 ----------'

'typedef uint16 QueSymbolT16; enum { ... }'

Public Enum QueSymbolT16 As Short
    blahblah
End Enum


'-- QuePositionDataType ----------'

'typedef struct { sint32 lat; sint32 lon; float altMSL; } QuePositionDataType;'

Public Structure QuePositionDataType
    Public lat As Integer
    Public lon As Integer
    Public altMSL As Single
End Structure


'-- QuePointHandle ----------'

'typedef uint32 QuePointHandle;'

'In VB use Integer.'

I assume that there is a reason that the C declare at the beginning is QueClosePoint and the pInvoke declare is QueRouteToPoint. Some tweaking may be necessary with this depending on alignment/packing issues and how the various items are used.

Stephen Martin