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

VB6经C++传递字符串至C#时出现截断问题

解决VB6→C++ DLL→.NET DLL的字符串传递问题

一、核心问题根源

VB6默认调用外部DLL时,传递的是ANSI编码的LPSTR(8位字符指针),而非COM标准的BSTR(带长度前缀的16位Unicode字符串)。你之前在C++中错误将参数声明为BSTR,导致把ANSI字符串的字节当成BSTR结构解析(BSTR前4字节是长度值,后续是Unicode字符),才出现乱码+仅最后一个字符正常的异常。

二、具体解决方案

方案1:转成标准Unicode字符串传递(优先实现可读字符串)

1. 修正C++ DLL的导出函数参数

将参数从BSTR改为LPCSTR,正确接收VB6传来的ANSI字符串:

// 错误声明(导致乱码)
// extern "C" __declspec(dllexport) void ProcessString(BSTR vbStr);

// 修正后的正确声明
extern "C" __declspec(dllexport) void ProcessString(LPCSTR vbAnsiStr);

2. C++内转Unicode并封装为BSTR传给.NET

利用Windows API将ANSI字符串转成宽字符,再封装为COM标准的BSTR,确保.NET能正确解析:

#include <comutil.h>
#pragma comment(lib, "comsuppw.lib")

extern "C" __declspec(dllexport) void ProcessString(LPCSTR vbAnsiStr)
{
    // 计算宽字符所需长度
    int wideLen = MultiByteToWideChar(CP_ACP, 0, vbAnsiStr, -1, NULL, 0);
    wchar_t* wideStr = new wchar_t[wideLen];
    MultiByteToWideChar(CP_ACP, 0, vbAnsiStr, -1, wideStr, wideLen);

    // 封装为BSTR(自动处理长度前缀)
    BSTR bstr = SysAllocString(wideStr);

    // 调用.NET COM对象的方法,传入BSTR
    YourDotNetComInstance->ProcessString(bstr);

    // 释放资源
    SysFreeString(bstr);
    delete[] wideStr;
}

3. .NET COM端直接接收字符串

.NET会自动将BSTR转换为CLR字符串,直接声明string类型参数即可:

[ComVisible(true)]
public interface IYourComInterface
{
    void ProcessString(string input);
}

[ComVisible(true)]
public class YourDotNetComClass : IYourComInterface
{
    public void ProcessString(string input)
    {
        // 此处可获取完整的"ABCDEFGHI"字符串
    }
}

方案2:直接传递字节数组(适配特殊编码场景)

如果VB6传递的是自定义8位编码字符串,可跳过编码转换,直接传递字节数组:

1. C++端封装字节数组为SAFEARRAY

extern "C" __declspec(dllexport) void ProcessString(LPCSTR vbAnsiStr)
{
    int strLen = strlen(vbAnsiStr);
    // 创建字节类型的SAFEARRAY
    SAFEARRAY* sa = SafeArrayCreateVector(VT_UI1, 0, strLen);
    BYTE* data;
    SafeArrayAccessData(sa, (void**)&data);
    memcpy(data, vbAnsiStr, strLen);
    SafeArrayUnaccessData(sa);

    // 调用.NET COM对象的字节数组处理方法
    YourDotNetComInstance->ProcessBytes(sa);

    SafeArrayDestroy(sa);
}

2. .NET端接收字节数组并转字符串

[ComVisible(true)]
public interface IYourComInterface
{
    void ProcessBytes([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UI1)] byte[] inputBytes);
}

[ComVisible(true)]
public class YourDotNetComClass : IYourComInterface
{
    public void ProcessBytes(byte[] inputBytes)
    {
        // 按对应编码转字符串,例如GB2312或系统默认ANSI编码
        string str = Encoding.GetEncoding("GB2312").GetString(inputBytes);
    }
}

三、关键验证点

  • VB6中声明DLL函数时必须加ByVal,确保传递的是字符串指针而非指针的指针:
    Declare Sub ProcessString Lib "YourCppDll.dll" (ByVal vbStr As String)
    
  • C导出函数必须加extern "C",避免C名字修饰导致VB6找不到函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:00:09