将字符串从VB6传递到C++再到C#,字符串被截断

问题描述 投票:0回答:1

我有无法更改的VB6代码,从外部dll调用函数。我正在用我正在编写的 C++ dll 替换外部 dll,它将通过 COM 调用我正在编写的 .NET dll。我可以控制 C++ 和 C#。

VB6 调用 dll 函数如下:

Declare Sub IEsend _
    Lib "IEEE_32M1.DLL" _
    Alias "_ieee_send@16" (ByVal addr As Long, _
                           ByVal s As String, _
                           ByVal l As Long, _
                           status As Long)

C# 通过 COM 公开函数供 C++ 调用

namespace IEEE_32MCOM
{
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [Guid("41C9877D-C110-4CBC-9E1B-4507D220DBCD")]
    public interface IIEEE_32MCOM
    {
        void _ieee_sendCOM(int addr, string s, int l, ref int status);
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [Guid("FE506B77-AD6B-4C37-97E2-A7A5DDE0CA52")]
    public class IEEE_32MCOMClass : IIEEE_32MCOM
    {
        public void _ieee_sendCOM(int addr, string s, int l, ref int status)
        {
            // .NET stuff here
        }
    }
}

C++ 头文件

#pragma once
#include <string>
#import "IEEE_32MCOM.tlb" raw_interfaces_only, named_guids

extern "C"
{
#pragma comment(linker, "/EXPORT:ieee_send=_ieee_send@16")
    __declspec(dllexport) void __stdcall ieee_send(long addr, BSTR cmd, long l, long* status);
}

IEEE_32MCOM::IIEEE_32MCOM* myInterface;

void init();

C++代码文件

#pragma comment(lib, "IEEE_32MCOM.tlb")
#include "pch.h"
#include "IEEE_32M1.h"

extern "C" __declspec(dllimport) void _ieee_sendCOM(long addr, BSTR cmd, long l, long* status);

void __stdcall ieee_send(long addr, BSTR cmd, long l, long* status)
{
    init();
    myInterface->_ieee_sendCOM(addr, cmd, l, status);
}

void init()
{
    HRESULT hr = CoCreateInstance(
        __uuidof(IEEE_32MCOM::IEEE_32MCOMClass),
        NULL,
        CLSCTX_ALL,
        IEEE_32MCOM::IID_IIEEE_32MCOM,
        (void**)&myInterface);
    if (FAILED(hr))
    {
        _com_error e(hr);
    }
}

经过大量研究,调用链正在工作 - 我对 C++ 不太流利。

问题在于从 VB6 传递的字符串似乎是 8 位字符,而 C++ 中的 BSTR 呈现为 16 位字符。

传递9个字符串“ABCDEFGHI”,

C++ 看到

䉁䑃䙅䡇I

C# 看到

䉁䑃䙅䡇

我不介意在 C# 中转换为人类可读的字符串,实际上我更喜欢它。但可以看出,C# 中的字符串缺少最后一个字符

检查字节,

var bytes = Encoding.Unicode.GetBytes(s);
产生 8 个字节,其中包括前 8 个字符
65, 66, ..., 72
,缺少最后一个字符
73
或“I”。

我相信我仅限于 COM 的 BSTR,但是当字符数为奇数时它会截断一个字符。如何将整个字符串传递给 .NET?我希望首先将整个人类可读的字符串从 C++ 传递到 C#,但我可以通过任何方式完成这项工作。

c# c++ com vb6
1个回答
0
投票

问题在于 从 VB6 传递的字符串似乎是 8 位字符,而 C++ 中的 BSTR 则呈现为 16 位字符。

这正是正在发生的事情。 因此,您需要将 DLL 更改为 not 接受字符串作为

BSTR
,而是作为
char*
,然后在将其传递给 C# 时将其 convert
BSTR
/
wchar_t*

例如:

void __stdcall ieee_send(long addr, const char* cmd, long l, long* status)
{
    init();
    myInterface->_ieee_sendCOM(addr, _bstr_t(cmd), l, status);
}
© www.soinside.com 2019 - 2024. All rights reserved.