我已经尝试了各种方法的许多不同组合来编组这个调用。这是一个 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。我已经联系 STMicroelectronics 关于如何与这个 DLL 接口,但到目前为止他们没有任何帮助。DLL 中的其余调用非常简单,但我必须让这个调用开始,因为它是关于实际连接的 JTAG 设备的信息。
更新(20 年 6 月 12 日)以添加实际的调用函数,现在调用函数将结构从非托管结构复制到托管结构。但是对 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);
}