C# 调用一个 DLL 函数,该函数返回一个指向结构数组的指针

2023-12-05

我尝试了各种方法的许多不同组合来封送此调用。这是一个 DLL,它返回一个指向结构数组的指针。像 debugPort 这样的类型实际上是枚举。

/**
* \struct debugConnectParameters 
* \brief Get device characterization and specify connection parameters through ST-LINK interface. 
*/ 
typedef struct debugConnectParameters { 
    debugPort dbgPort;        /**< Select the type of debug interface #debugPort. */ 
    int index;                /**< Select one of the debug ports connected. */ 
    char serialNumber[33];    /**< ST-LINK serial number. */ 
    char firmwareVersion[20]; /**< Firmware version. */ 
    char targetVoltage[5];    /**< Operate voltage. */ 
    int accessPortNumber;     /**< Number of available access port. */ 
    int accessPort;           /**< Select access port controller. */ 
    debugConnectMode connectionMode; /**< Select the debug CONNECT mode #debugConnectMode. */ 
    debugResetMode resetMode; /**< Select the debug RESET mode #debugResetMode. */ 
    int isOldFirmware;        /**< Check Old ST-LINK firmware version. */ 
    frequencies freq;         /**< Supported frequencies #frequencies. */ 
    int frequency;            /**< Select specific frequency. */ 
    int isBridge;             /**< Indicates if it's Bridge device or not. */ 
    int shared;               /**< Select connection type, if it's shared, use ST-LINK Server. */ 
} debugConnectParameters;

int getStLinkList(debugConnectParameters** stLinkList, int shared);
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public unsafe struct debugConnectParameters
    {
        debugPort dbgPort;                  /**< Select the type of debug interface #debugPort. */
        int index;                          /**< Select one of the debug ports connected. */
        fixed char serialNumber[33];        /**< ST-LINK serial number. */
        fixed char firmwareVersion[20];     /**< Firmware version. */
        fixed char targetVoltage[5];        /**< Operate voltage. */
        int accessPortNumber;               /**< Number of available access port. */
        int accessPort;                     /**< Select access port controller. */
        debugConnectMode connectionMode;    /**< Select the debug CONNECT mode #debugConnectMode. */
        debugResetMode resetMode;           /**< Select the debug RESET mode #debugResetMode. */
        int isOldFirmware;                  /**< Check Old ST-LINK firmware version. */
        frequencies freq;                   /**< Supported frequencies #frequencies. */
        int frequency;                      /**< Select specific frequency. */
        int isBridge;                       /**< Indicates if it's Bridge device or not. */
        int shared;                         /**< Select connection type, if it's shared, use ST-LINK Server. */
    }
    [DllImport(dllPath + "CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public unsafe extern static int getStLinkList(
        debugConnectParameters** stLinkList,
        int shared
        );

我尝试替换使用“out”和“ref”选项。我试图找到它喜欢的 IntPtr 版本。我不断收到:System.AccessViolationException。我已经就如何与这个 DLL 进行交互联系了 STMicroElectronics,但到目前为止他们还没有提供任何帮助。 DLL 中的其余调用非常简单,但我必须让这个调用正常工作才能开始,因为它是有关实际连接的 JTAG 设备的信息。

更新 (6/12/20) 以添加实际的调用函数,现在调用函数将结构从非托管结构复制到托管结构。但调用 getStLinkList() 仍然不起作用。

        public unsafe static int GetDeviceList(ref debugConnectParameters[] debugParams, int maxCount)
        {
            IntPtr unManagedListPtr = Marshal.AllocHGlobal(sizeof(debugConnectParameters*));
            IntPtr *unManagedListPtrPtr = &unManagedListPtr;
            int count = getStLinkList((debugConnectParameters**)unManagedListPtrPtr, 0);
            IntPtr copyPtr = unManagedListPtr;
            if (count > maxCount) count = maxCount;
            for (int i = 0; i < count; i++)
            {
                debugParams[i] = (debugConnectParameters)Marshal.PtrToStructure(copyPtr, typeof(debugConnectParameters));
                copyPtr += sizeof(debugConnectParameters);
            }
            Marshal.FreeHGlobal(unManagedListPtr);
            return (count);
        }

我也尝试过这些改变但没有运气。我仍然看到访问违规。尝试读取或写入受保护的内存。


    [DllImport(dllPath + "CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        unsafe private static extern int getStLinkList(
            ref IntPtr stLinkList,
            int shared
            );
    unsafe public static int GetDeviceList(List<debugConnectParameters> list)
    {
        IntPtr unManagedListPtr = Marshal.AllocHGlobal(sizeof(debugConnectParameters*));
        IntPtr copyPtr = unManagedListPtr;

            int count = getStLinkList(ref unManagedListPtr, 0);

            if (count > 10) count = 10;
            for (int i = 0; i < count; i++)
            {
                debugConnectParameters parameter = (debugConnectParameters)Marshal.PtrToStructure(copyPtr, typeof(debugConnectParameters));
                list.Add(parameter);
                copyPtr += sizeof(debugConnectParameters);
            }

            Marshal.FreeHGlobal(unManagedListPtr);
            return (count);
    }

在调用时有两件事对我们不利getStLinkList特别是“CubeProgrammer_API.dll”库的功能。如果不更正它们,库将无法工作,即使是在 C++ 中也是如此。

首先,在中找到该库的依赖项api/libSTM32CubeProgrammer 安装的文件夹并非全部针对 x64 编译。中的版本bin文件夹是,这些是您希望在运行时可用的库。我通过将工作目录设置为项目调试设置中的该目录来完成此操作。这是通过检查每个 DLL 的目标机器来验证的api/lib and bin文件夹。

二、调用前需要初始化“CubeProgrammer_API.dll”getStLinkList通过致电setLoadersPath and setDisplayCallbacks功能。第一个函数必须提供“Flash Loader”的路径,即bin/FlashLoader就我而言。这setDisplayCallbacksfunction 采用三个函数指针的结构。

下面的示例可能不是类型封送的最佳示例,但它将说明该过程。

public static class CubeProgrammerApi
{
    public enum DebugConnectionMode
    {
        NormalMode = 0,
        HotplugMode = 1,
        UnderResetMode = 2,
        PreResetMode = 3
    }
    
    public enum DebugResetMode
    {
        SoftwareReset = 0,
        HardwareReset = 1,
        CoreReset = 2
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public class Frequencies
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
        uint[] JtagFrequency;
        uint JTagFrequencyNumber;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
        uint[] SwdFrequency;
        uint SwdFrequencyNumber;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public class DebugConnectParameters
    {
        DebugPort DebugPort;
        public int Index;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)]
        public string SerialNumber;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
        public string FirmwareVersion;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
        public string TargetVoltage;
        public int AccesPortNumber;
        public int AccessPort;
        public DebugConnectionMode connectionMode;
        public DebugResetMode resetMode;
        public bool IsOldFirmware;
        public Frequencies Freqencies;
        public int Frequency;
        public bool IsBridge;
        public int Shared;
    }
    
    public delegate void LogMessageReceived(int messageType, [MarshalAs(UnmanagedType.LPWStr)] string message);
    public delegate void InitProgressBar();
    public delegate void ProgressBarUpdateReceived(int currentProgress, int total);

    internal static class NativeMethods
    {
        public struct DisplayCallbacks
        {
            public InitProgressBar initProgressBar;
            public LogMessageReceived logMessage;
            public ProgressBarUpdateReceived loadBar;
        }

        [DllImport("CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "setLoadersPath")]
        internal static extern void SetLoadersPath(string path);

        [DllImport("CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "setDisplayCallbacks")]
        internal static extern void SetDisplayCallbacks(ref DisplayCallbacks callbacks);

        [DllImport("CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "getStLinkList")]
        internal static extern int GetStLinkList(IntPtr stLinkList, uint shared);

        [DllImport("CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl)]
        internal static extern void deleteInterfaceList();

        [DllImport("CubeProgrammer_API.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "reset")]
        internal static extern int Reset([MarshalAs(UnmanagedType.U4)] DebugResetMode rstMode);
    }

    public static void SetLoadersPath(string path)
    {
        NativeMethods.SetLoadersPath(path);
    }

    public static void SetDisplayCallbacks(InitProgressBar initProgressBar, LogMessageReceived messageReceived, ProgressBarUpdateReceived progressBarUpdate)
    {
        NativeMethods.DisplayCallbacks callbacksHandle;

        callbacksHandle.initProgressBar = initProgressBar;
        callbacksHandle.logMessage = messageReceived;
        callbacksHandle.loadBar = progressBarUpdate;

        NativeMethods.SetDisplayCallbacks(ref callbacksHandle);
    }

    public static IList<DebugConnectParameters> GetStLinkProgrammers(bool shared = false)
    {
        var listPtr = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>());
        var parametersList = new List<DebugConnectParameters>();

        try
        {
            var size = Marshal.SizeOf<DebugConnectParameters>();
            var numberOfItems = NativeMethods.GetStLinkList(listPtr, shared ? 1U : 0U);
            var listDereference = Marshal.PtrToStructure<IntPtr>(listPtr);

            for (var i = 0; i < numberOfItems; i++)
            {
                var currentItem = Marshal.PtrToStructure<DebugConnectParameters>(listDereference + (i * size));

                parametersList.Add(currentItem);
            }

            NativeMethods.deleteInterfaceList();
        }
        finally
        {
            Marshal.FreeHGlobal(listPtr);
        }

        return parametersList;
    }

    public static void FreeStLinkProgrammers()
    {
        NativeMethods.deleteInterfaceList();
    }
}

以及主要:

class Program
    {
        static void Main(string[] args)
        {
            CubeProgrammerApi.SetLoadersPath(@"C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeProgrammer\bin\FlashLoader");
            CubeProgrammerApi.SetDisplayCallbacks(InitProgressBar, ReceiveMessage, ProgressBarUpdate);
            var stLinkList = CubeProgrammerApi.GetStLinkProgrammers();

            foreach (var stlink in stLinkList)
            {
                Console.WriteLine("{0} {1}", stlink.Index, stlink.SerialNumber);
            }

            Console.WriteLine("Press ENTER to exit");
            Console.ReadLine();

            CubeProgrammerApi.FreeStLinkProgrammers();
        }

        static void ReceiveMessage(int messgaeType, string message)
        {

        }

        static void InitProgressBar()
        {

        }

        static void ProgressBarUpdate(int currentProgress, int total)
        {

        }
    }

这将输出以下内容,并附加两个调试器,分别是 STLink V3 和 STLink V2。这应该能让您足够了解要使用的正确类型。

0 002F001D3038511834333935
1 34FF6D065250343847110943
Press ENTER to exit
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 调用一个 DLL 函数,该函数返回一个指向结构数组的指针 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • 嵌套接口:将 IDictionary> 转换为 IDictionary>?

    我认为投射一个相当简单IDictionary
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 将多个表映射到实体框架中的单个实体类

    我正在开发一个旧数据库 该数据库有 2 个具有 1 1 关系的表 目前 我为每个定义的表定义了一种类型 1Test 1Result 我想将这些特定的表合并到一个类中 当前的类型如下所示 public class Result public
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐

  • 连接向量中的相邻字符串

    Given qz lt quantile c 1 2 3 4 5 6 7 8 9 10 c 0 0 0 2 0 4 0 6 0 8 1 0 我想从分位数创建一个标签向量 目前 我这样做 zlab lt c paste paste sprin
  • 从另一个 2D 数组的元素中过滤 2D 数组

    我有两组数字元素存储为二维数组 使用以下方法从列中获取值 getValues 一个是完整列表 另一个是部分列表 我想要一个返回完整列表减去部分列表的函数 The partialListArr可能包含重复项 这fullListArr做 不是
  • Backbone:视图内的视图列表

    让我先展示我需要什么 以便您能够理解我的问题 我有一个联系人视图 例如 ContactView Backbone View extend template template Name E mail Phones render functio
  • R 语言的基本等值线州地图

    我很抱歉 因为我很确定这是一个基本问题 我想做的就是使用maps包在R中创建一个非常简单的等值线地图 这是我第一次尝试在 R 中映射任何数据 我所在的地区是美国本土 48 个州 包括华盛顿特区 这是我想要绘制的数据集的前几行 gt head
  • 调试密钥和签名密钥之间的区别

    您好 我正在尝试获取我的签名证书的签名密钥 MD5 指纹 有人可以告诉我签名密钥和调试密钥之间的区别吗 我能够指纹调试密钥 但为了获取签名密钥指纹 我很困惑 keytool list alias alias name keystore my
  • 如何从VB.Net中的DataGridView获取单元格值?

    我有一个问题 如何从 datagridview 的单元格中获取值 id p w post 1 1234 A 2 4567 S 3 6789 A 我想在文本框中输入3 该怎
  • 三元运算符的语法错误[重复]

    这个问题在这里已经有答案了 我是Python新手 我正在尝试使用具有这种格式的三元运算符 我认为是这样 value true if
  • 加特林如何在两个场景之间传递价值?

    我的脚本中有两个场景 我想将 CreateId 的值传递给第二个场景 我在第一个场景中保存了 CreateId 错误说 未定义名为 CreateId 的属性 jsonPath id find 0 exists 什么也没找到 场景 1 val
  • WinForms 中具有 alpha 通道透明度/不透明度的启动屏幕

    如何在 WinForms 中使用具有 alpha 通道透明度 不透明度的图像来实现启动屏幕 看一眼C 中的每像素 Alpha 混合
  • 文化特定数据注释

    我正在尝试获取特定于文化的数据注释 DisplayFormat DataFormatString 0 d public DateTime Date get set 我认为这会起作用 因此 在美国 它会显示 DD MM yyyy 在欧洲 它会
  • Snow Leopard、Django 和 PIL 的问题

    自从升级到 Snow Leopard 以来 我在让 Django 和 PIL 正常工作时遇到了一些问题 我已经安装了 freetype libjpeg 和 PIL 它告诉我 TKINTER support ok JPEG support o
  • 在 kotlin lambda 内部返回时“此处不允许返回”

    我使用 lambda 来处理异步调用的回调 我想在调用方法之外定义回调以避免使用庞大的方法 但我似乎无法在 lambda 中使用早期返回 这使得代码不必要地难以阅读 我尝试将 lambda 定义为变量 但 return 在 lambda 内
  • Promise 的动态顺序执行

    我有需要按顺序运行的动态数量的承诺 我了解如何按顺序运行承诺 但我无法成功地使其与许多可能变化的承诺保持动态 这是我发现静态执行此操作的一种方法如何兑现一个又一个的承诺 function waitFor timeout return new
  • Python实时绘制ROS数据

    我正在尝试使用 python 绘制传入计算机的实时数据 数据来自 ROS 主题 我使用 rospy 订阅该主题以获取数据 这是我写的代码 import rospy from sensor msgs msg import ChannelFlo
  • 如何使我的所有网址都无扩展名,且不带尾部斜杠。并将 .php 和尾部斜杠重定向为无?

    我想让我的所有网址统一干净 这意味着我所有的 URL 都没有扩展名 也没有尾部斜线 并且如果一个人确实输入了 php或尾部斜杠 它只会将用户重定向到干净的 URL Example example com blog file php and
  • 如何对 UTF-8 字符使用 String 方法?

    如何对 UTF 8 字符使用 String 方法 例如 我有一个带有西里尔字符的字符串 所以当我使用string upcase它不起作用 Ruby 仅支持字母的大小写转换A Z and a z 原因很简单 其他字母的大小写转换没有明确定义
  • Resteasy 客户端的自定义 Jackson 序列化器

    是否可以为 Resteasy 客户端注册自定义 Jackson JSON 序列化器 我尝试过做类似的事情 ResteasyClient client new ResteasyClientBuilder register new Custom
  • 为什么没有更多的迭代器随机访问?

    我正在尝试了解有关 C 中的 STL 迭代器的更多信息 我理解不同的数据结构如何具有不同的迭代器 但我不明白为什么有些迭代器不是随机访问 例如 为什么 LinkedList 迭代器不是随机访问迭代器 我知道 LinkedList 本身并不是
  • 汇编 (,%eax,4)

    如果我的命令行之一显示 jmp 0x804a180 eax 4 这意味着什么 我特别询问是因为第一个逗号之前没有值 而且我不确定地址之前的 到底是什么意思 该指令跳转到其值位于计算得出的地址处的位置 eax 4 0x804a180 The
  • C# 调用一个 DLL 函数,该函数返回一个指向结构数组的指针

    我尝试了各种方法的许多不同组合来封送此调用 这是一个 DLL 它返回一个指向结构数组的指针 像 debugPort 这样的类型实际上是枚举 struct debugConnectParameters brief Get device cha