You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WinCE7下从C++ DLL向C#返回结构体数组的技术问询

我来帮你搞定WinCE 7环境下C++ DLL向C#返回结构体数组的问题,结合你给出的代码片段,咱们一步步拆解实现细节:

第一步:完善C++ DLL的实现

首先得把你的代码补全,还要解决内存管理字符串复制的问题,同时要确保函数能被正确导出:

#include <windows.h>
#include <wlanapi.h>

// 定义共享结构体,注意字符数组的长度要包含终止符
struct AvailableNetworkList {
    char strProfileName[7];  // 7个字符空间(含'\0')
    ULONG WLanSignalQuality;
};

// 导出函数,用extern "C"避免名字修饰,__declspec(dllexport)标记导出
extern "C" __declspec(dllexport) 
BOOL GetAvailableNetworkLists(OUT AvailableNetworkList** data, OUT int* length) {
    if (!data || !length) return FALSE;

    HANDLE hClient = NULL;
    DWORD dwNegotiatedVersion = 0;
    DWORD dwResult = WlanOpenHandle(2, NULL, &dwNegotiatedVersion, &hClient);
    if (dwResult != ERROR_SUCCESS) return FALSE;

    WLAN_AVAILABLE_NETWORK_LIST* pList = NULL;
    dwResult = WlanGetAvailableNetworkList(hClient, NULL, 0, NULL, &pList);
    if (dwResult != ERROR_SUCCESS) {
        WlanCloseHandle(hClient, NULL);
        return FALSE;
    }

    *length = pList->dwNumberOfItems;
    // 分配结构体数组内存
    *data = new AvailableNetworkList[*length];

    for (DWORD i = 0; i < pList->dwNumberOfItems; i++) {
        // 复制信号质量
        (*data)[i].WLanSignalQuality = pList->Network[i].wlanSignalQuality;
        // 复制配置文件名,注意截断到6个字符(留一个位置给'\0')
        strncpy_s((*data)[i].strProfileName, sizeof((*data)[i].strProfileName), 
                  pList->Network[i].strProfileName, _TRUNCATE);
    }

    WlanFreeMemory(pList);
    WlanCloseHandle(hClient, NULL);
    return TRUE;
}

// 必须提供内存释放函数,否则C#无法回收C++分配的内存
extern "C" __declspec(dllexport)
void FreeAvailableNetworkLists(IN AvailableNetworkList* data) {
    if (data) {
        delete[] data;
    }
}
第二步:C#端的互操作配置

在C#里需要定义匹配的结构体和DLL导入函数,注意WinCE环境的字符集和内存布局:

using System;
using System.Runtime.InteropServices;

namespace WinCE_WLAN
{
    // 匹配C++的结构体布局,指定ANSI字符集(WinCE默认ANSI)
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct AvailableNetworkList
    {
        // 对应C++的char[7],指定固定长度字符串
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)]
        public string strProfileName;
        public uint WLanSignalQuality;
    }

    public class WlanHelper
    {
        // 导入DLL中的获取函数,注意调用约定和参数类型
        [DllImport("YourDllName.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern bool GetAvailableNetworkLists(out IntPtr networkListPtr, out int length);

        // 导入内存释放函数
        [DllImport("YourDllName.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void FreeAvailableNetworkLists(IntPtr networkListPtr);

        public static AvailableNetworkList[] GetNetworks()
        {
            IntPtr listPtr = IntPtr.Zero;
            int length = 0;
            AvailableNetworkList[] networks = null;

            try
            {
                bool success = GetAvailableNetworkLists(out listPtr, out length);
                if (!success || length == 0) return null;

                // 分配C#数组,逐个 Marshal 结构体
                networks = new AvailableNetworkList[length];
                int structSize = Marshal.SizeOf(typeof(AvailableNetworkList));
                for (int i = 0; i < length; i++)
                {
                    IntPtr itemPtr = IntPtr.Add(listPtr, i * structSize);
                    networks[i] = (AvailableNetworkList)Marshal.PtrToStructure(itemPtr, typeof(AvailableNetworkList));
                }
            }
            finally
            {
                // 无论成功失败,都要释放C++分配的内存
                if (listPtr != IntPtr.Zero)
                {
                    FreeAvailableNetworkLists(listPtr);
                }
            }

            return networks;
        }
    }
}
关键注意事项(WinCE特有的坑)
  • 字符集问题:WinCE默认使用ANSI字符集,所以C#结构体必须指定CharSet.Ansi,否则字符串会乱码。
  • 内存管理:WinCE下C#无法直接释放C++用new分配的内存,必须在DLL中提供释放函数,并且在C#的finally块中调用,避免内存泄漏。
  • 结构体对齐:确保C++和C#的结构体布局一致,LayoutKind.Sequential会严格按照成员顺序排列,避免因对齐差异导致的数据错误。
  • 字符串长度:C++中char strProfileName[7]最多存6个有效字符(加终止符),所以复制时要注意截断,避免缓冲区溢出。

内容的提问来源于stack exchange,提问作者samiaj

火山引擎 最新活动