如何将这个不安全的DLL调用重构为在C#中使用IntPtr的调用

问题描述

我正在尝试使用C语言编写的库在.NET中为HackRF One构建应用程序... https://github.com/mossmann/hackrf/blob/master/host/libhackrf/src/hackrf.c

这是DLL调用...

[DllImport(dllname)]
public static extern unsafe hackrf_device_list_t* hackrf_device_list();

哪个返回指向以下对象的指针...

public struct unsafe hackrf_device_list_t
{
    public byte** serial_numbers;
    public hackrf_usb_board_id* usb_board_ids;
    public int* usb_device_index;
    public int devicecount;
    public void** usb_devices;
    public int usb_devicecount;
};

public enum hackrf_usb_board_id
{
    USB_BOARD_ID_JAWBREAKER = 0x604B,USB_BOARD_ID_HACKRF_ONE = 0x6089,USB_BOARD_ID_RAD1O = 0xCC15,USB_BOARD_ID_INVALID = 0xFFFF,};

我想将其放入普通的C#受管对象中。这就是它的使用方式...

unsafe public static hackrf_device_info[] HackrfDeviceList() // Enumerates connected hackrf devices
{
    libhackrf.hackrf_device_list_t* ptr = libhackrf.hackrf_device_list();
    //if (ptr == null) throw new Exception("Null pointer returned");
    if (ptr == null) return new hackrf_device_info[0];
    libhackrf.hackrf_device_list_t devs = *ptr;
    hackrf_device_info[] ret = new hackrf_device_info[devs.devicecount];
    for (int i = 0; i < devs.devicecount; i++)
    {
        hackrf_device_info dev = new hackrf_device_info {
            serial_number = PtrToStr(devs.serial_numbers[i]),usb_board_id = (hackrf_board)devs.usb_board_ids[i],usb_device_index = devs.usb_device_index[i]
        };
        ret[i] = dev;
    }
    return ret;
}

全部来自我发现的git repo ... https://github.com/makar853/nethackrf

解决方法

尝试以下方法,看看尺寸是否合适。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication169
{
    class Program
    {
        public const string dllname = @"hackrf.dll";
        [StructLayout(LayoutKind.Sequential)]
        public struct hackrf_device_list_t
        {
            public byte[][] serial_numbers;
            public hackrf_usb_board_id usb_board_ids;
            public int usb_device_index;
            public int devicecount;
            public IntPtr usb_devices;
            public int usb_devicecount;
        };
        public enum hackrf_usb_board_id
        {
            USB_BOARD_ID_JAWBREAKER = 0x604B,USB_BOARD_ID_HACKRF_ONE = 0x6089,USB_BOARD_ID_RAD1O = 0xCC15,USB_BOARD_ID_INVALID = 0xFFFF,};
        [DllImport(dllname)]
        public static extern IntPtr hackrf_device_list();

        static void Main(string[] args)
        {
            IntPtr ptr = hackrf_device_list();
            int size = Marshal.SizeOf(ptr);

            hackrf_device_list_t hackrf = new hackrf_device_list_t();
            int structuresize = Marshal.SizeOf(hackrf);
        }
    }
  
}