передача строки BSTR в качестве периметра между управляемым и неуправляемым кодом (взаимодействие COM) - PullRequest
0 голосов
/ 09 января 2019

Во время работы над com interop я следовал руководству по этой ссылке . Код работает нормально, так как я сделал некоторые изменения в зависимости от моих требований, но проблема возникает при работе со строкой. Я использую Строка BSTR здесь как периметр здесь. Вот функция в C #, которую я вызываю из C ++

  public  string ShowDialog([MarshalAs(UnmanagedType.BStr)] string stringToPrint)
    {
      //  Console.WriteLine(" Enter TOTP input:");
       // stringToPrint = Console.ReadLine();

        if (stringToPrint == "111111")
        {

            MessageBox.Show("true");



        }
        else
        {
            MessageBox.Show("false");

        }

        return stringToPrint;
    }

вот мой основной раздел кода C ++ кода, в котором выполняются вызовы

CoInitialize(NULL);

MyInterop::IMyDotNetInterfacePtr pDotNetCOMPtr;

HRESULT hRes = pDotNetCOMPtr.CreateInstance(MyInterop::CLSID_MyDotNetClass);
if (hRes == S_OK)
{

    BSTR lResult ;

    cout << "enter TOTP input" << endl;

    _bstr_t bstrStatus = SysAllocString(L"111111");

    pDotNetCOMPtr->ShowDialog(bstrStatus,&lResult);

    SysFreeString(bstrStatus);


}

CoUninitialize();

system("pause");

вот вывод enter image description here

Проблемы, с которыми я сталкиваюсь, следующие:

  • Строка BSTR не возвращается на консоль после того, как она передана из кода c ++, хотя я использую функцию возврата в c #
  • Можно ли динамически вставлять ввод в консоль, поскольку я использую SysAllocString ("") , что делает его несколько жестко запрограммированным.

1 Ответ

0 голосов
/ 09 января 2019

Когда вы используете Visual Studio и директиву #import, сгенерированный код использует _bstr_t , который является классом интеллектуальной оболочки над BSTR (необработанный тип Windows).

Итак, вам не нужно использовать ни SysAllocString, ни SysFreeString, вы можете просто использовать _bstr_t очень естественно. Например, в вашем случае, если ваша подпись метода C # выглядит следующим образом:

public string ShowDialog(string stringToPrint) // you don't need the MarshalAs here, the TLB will build it as a BSTR

тогда вы можете использовать код C ++, например:

... other imports or includes
// import mscorlib so we have a full generated cool code (I recommend not to use raw_interfaces_only)
// we rename 'or' to something that doesn't pose problems. Your mileage can vary depending on your building context...
#import "C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb" rename("or","whatever")
#import "C:\myPath\MyClassLibrary1.tlb" // adapt to your path

int main()
{
  CoInitialize(NULL);
  {
    MyClassLibrary1::_Class1Ptr ptr;
    HRESULT hr = ptr.CreateInstance(__uuidof(MyClassLibrary1::Class1)); // should return S_OK/0

    _bstr_t input = L"111111";
    _bstr_t res = ptr->ShowDialog(input); // assign the return string
    wprintf(L"res:%s\n", res.GetBSTR()); // output (unicode) result to console
  }
  CoUninitialize();
}

Вы также можете написать это прямо:

_bstr_t res = ptr->ShowDialog(L"111111");

// или это (с автоматическим преобразованием ANSI в Unicode)

_bstr_t res = ptr->ShowDialog("111111");

Все _bstr_t автоматически распределяются и освобождаются.

...