管理 C++ C# 中的 Garmin API

发布于 2024-08-04 09:36:16 字数 2589 浏览 4 评论 0原文

我想在VB.Net Compact Framework项目中调用Garmin API。 API 采用 C++ 语言,因此我正在制作一个 C# dll 项目作为 API dll 和 VB.NET 之间的中间方式。我在执行代码时遇到一些问题,因为它在 QueCreatePoint 调用中抛出 NotSupportedException (我认为是错误的参数类型)。下面是 C++ API 代码和我的 C# 工作。

C++ 函数原型和 C# P/Invoke 调用:

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;

在 C# 中,我将其作为 uint var 进行管理。

这是我当前调用所有这些的 C# 函数:

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 want to call Garmin API 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 throws a NotSupportedException (bad arguments type, I think) in the QueCreatePoint call. Below 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 a 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; 
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

快乐很简单 2024-08-11 09:36:16

您应该能够直接从 VB 对这些使用 pInvoke,而无需 C# 包装器(或 C++ 包装器)。声明应该是这样的:

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

我认为开头的 C 声明是 QueClosePoint 而 pInvoke 声明是 QueRouteToPoint 是有原因的。根据对齐/包装问题以及各种物品的使用方式,可能需要进行一些调整。

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.

秋凉 2024-08-11 09:36:16

您始终可以创建一个 CPP/CLI 项目,用托管 API 包装本机 API。通常,以这种方式编写托管包装器比使用 DllImprt 要简单得多。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文