2009-09-11 6 views
2

Je souhaite appeler le Garmin API dans le projet VB.Net Compact Framework. L'API est en C++, donc je fais un projet C# dll comme moyen intermédiaire entre API dll et VB.NET. J'ai quelques problèmes lors de l'exécution de mon code car il lance un NotSupportedException (mauvais type d'arguments, je pense) dans l'appel QueCreatePoint. Voici le code de l'API C++ et mon travail en C#.Gestion de l'API C++ Garmin en C#

C++ Fonctions prototype et C# P/Invoke Appels:

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; 

En C# je gère comme un uint var.

Et ceci est ma fonction actuelle C# pour appeler tout cela:

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

Répondre

0

vous pouvez toujours créer un projet RPC/CLI qui enveloppera l'API native avec une API gérée. Habituellement, il est beaucoup plus simple d'écrire un wrapper géré de cette façon au lieu d'utiliser DllImprt.

+0

Wow, ça a l'air dur. Il y a un outil pour faire l'emballage? Ma connaissance de C est faible, et je n'ai aucune idée de l'emballage d'une API native. Je vois cette autre personne faire un Wrapper (http://christian-helle.blogspot.com/2008/02/integrating-with-garmin-mobile-xt.html), mais je ne peux pas l'utiliser dans .NET 1.1. C'est la raison pour laquelle j'utilise P/Invoke à la place. Merci. –

1

Vous devriez pouvoir utiliser pInvoke sur ceux-ci directement à partir de VB sans le wrapper C# (ou le wrapper C++). Les déclarations doivent être quelque chose le long de ces lignes:

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

Je suppose qu'il ya une raison pour laquelle le C déclarer au début est QueClosePoint et le Pinvoke DECLARE QueRouteToPoint. Certains ajustements peuvent s'avérer nécessaires en fonction des problèmes d'alignement/d'emballage et de la manière dont les différents éléments sont utilisés.