You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET调用Unicode非托管DLL,文件名参数后出现乱码,求原因

问题原因及解决方案

根本原因

非托管DLL中LPCTSTR在Unicode编译环境下等价于const wchar_t*(宽字符字符串),但你的.NET互调用代码里DllImport默认使用ANSI字符集,导致.NET将string转换为ANSI编码的单字节字符串传递给DLL,而DLL却按照宽字符格式解析,因此出现"a"后跟随乱码的情况——宽字符每个字符占2字节,ANSI的"a"是0x61,后续内存中的随机数据被错误当成宽字符的一部分解析。

修复步骤

1. 修正DllImport的字符集

在DllImport属性中显式指定CharSet.Unicode,确保.NET传递宽字符字符串:

[DllImport("SDK.DLL", CharSet = CharSet.Unicode)]
public static extern uint ProcessFileAPI(string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc, IntPtr lpProgProcParam, ref int pbCancel, ref TOptions1 options);

2. 匹配结构体内存对齐

非托管结构体用了#pragma pack(1),对应的.NET结构体需要添加StructLayout属性指定对齐规则,避免内存布局不一致:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TOptions1
{
    public bool bOption1;
    public bool bOption2;
}

3. 确认回调委托的调用约定

非托管回调LPPROGRESSPROC使用CALLBACK(即stdcall调用约定),.NET委托默认是StdCall,显式标注更稳妥:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void TProgressProc(byte btProgress, IntPtr lParam);

修正后的完整互调用代码

using System;
using System.Runtime.InteropServices;

namespace SDKAPI
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct TOptions1
    {
        public bool bOption1;
        public bool bOption2;
    }

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void TProgressProc(byte btProgress, IntPtr lParam);
}

namespace SDKAPI.Units
{
    public class SDKAPI
    {
        [DllImport("SDK.DLL", CharSet = CharSet.Unicode)]
        public static extern uint ProcessFileAPI(string lpSrcFileName, string lpDstFileName, TProgressProc pgrsproc, IntPtr lpProgProcParam, ref int pbCancel, ref TOptions1 options);
    }
}

完成上述修改后,字符串参数会以正确的Unicode宽字符形式传递给非托管DLL,乱码问题即可解决。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:55:55