供VBA调用的C++ DLL读取INI文件字符串编码异常问题
错误原因
- 字符编码匹配错误:VBA原生使用UTF-16(Unicode)编码字符串,调用C++ DLL时,输入String参数会自动转换为ANSI编码传入,但返回BSTR类型时VBA会默认按UTF-16解析,你的代码中存在多次冗余编码转换,导致字符乱码
- 缓冲区参数不规范:
GetPrivateProfileStringA要求传入的缓冲区大小参数是字符数,你的代码传了sizeof(localStr),虽然多字节字符集下char的大小是1字节暂时没问题,但属于不规范写法,切换字符集时很容易出错 - 冗余的VBA编码转换:你调用
StrConv(..., vbFromUnicode)属于多余操作,会把已经是UTF-16的字符串强制按单字节解析再转存为UTF-16,直接导致中长字符串乱码
修正方案
第一步:修改C++ DLL代码
统一使用Unicode接口,避免字符集不匹配问题:
BSTR __stdcall GetSectionEntry(LPCWSTR sSection, LPCWSTR sEntry) { // 文件名直接用宽字符定义,避免转义错误注意是双反斜杠 LPCWSTR gszINIfilename = L"C:\\test\\test.ini"; WCHAR localStr[1024] = {0}; // 统一用宽字符缓冲区,大小可按需调整 if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(gszINIfilename) && GetLastError() == ERROR_FILE_NOT_FOUND) { return SysAllocString(L""); } else { // 调用Unicode版本的INI读取API,缓冲区大小传数组元素个数 GetPrivateProfileStringW(sSection, sEntry, L"", localStr, _countof(localStr), gszINIfilename); return SysAllocString(localStr); } }
VS编译时字符集建议改为「使用Unicode字符集」,避免宏定义不匹配
第二步:修改VBA调用代码
删除冗余的编码转换,直接用简化版声明即可:
Declare PtrSafe Function GetSectionEntry Lib "test.dll" (ByVal sSection As String, ByVal sEntry As String) As String For i = 0 To 5 ' 不需要任何编码转换,直接输出即可 Debug.Print "Name = " & GetSectionEntry("Name", CStr(i)) Next i
内容的提问来源于stack exchange,提问作者Kris_R
相关产品推荐
相关产品推荐

