Как бы я назвал устаревший метод интерфейса DLL C++ с параметрами BSTR* и BSTR** из C#

Добрый день коллеги-разработчики

Я искал в Интернете в течение 2 дней, как сделать то, что мне нужно, и я пробовал много образцов без успеха. Однако это не значит, что я охватила все сайты — я думаю, что я слепа на один глаз и не вижу другим.

Во всяком случае, мне вручили лист бумаги с определением COM-интерфейса автоматизации и попросили разработать приложение C# для использования интерфейса и обратных вызовов соответственно.

Итак, начнем с простого (или я так думал) - сигнатура метода С++:

STDMETHODIMP CSimpleChatServer::CallMe(BSTR clientName, BSTR** returnMessage)

и подпись интерфейса:

HRESULT _stdcall CallMe([in] BSTR clientName, [in] BSTR** helloMessage);

И мне нужно вызвать это из C# - я установил интерфейс для ISimpleChatServer; следовательно, кодовый вызов, который я пытаюсь, похож.

string rtrnMsg = string.Empty; ImySimpleCom.CallMe("Robert", rtrnMsg)

Поскольку подпись является [in], я получаю исключение при попытке доступа к защищенной памяти.

Теперь я считаю, что он хочет, чтобы IntPtr был вторым параметром; однако все мои попытки добиться этого не увенчались успехом.

Пожалуйста, имейте в виду, что я не могу изменить библиотеку - это устаревший интерфейс "как есть", который нам нужно использовать еще некоторое время, и у провайдера нет никого, кто бы обновлял его соответствующим образом (на самом деле я думаю, что они не есть кому поработать).

Любая помощь будет приветствоваться.

С уважением, Роберт С.


person Robert Springer    schedule 03.11.2016    source источник
comment
Как вы создаете код для ImySimpleCom? Вы используете p/invoke или встроенные COM-функции .NET?   -  person Scott Chamberlain    schedule 03.11.2016
comment
Я не имел в виду, как вы создаете новый экземпляр, я имел в виду, как вы генерируете сам код для класса. Я обновил свой предыдущий комментарий, но вам, вероятно, нужно было обновить.   -  person Scott Chamberlain    schedule 03.11.2016
comment
ваше описание функции CallMe содержит два [in], но вы говорите, что хотите вернуть helloMessage... в этом случае объявите его [out, retval] и просто возьмите возвращаемое значение.   -  person AndersK    schedule 03.11.2016
comment
Прошу прощения - наверное, я не понимаю (я ценю ваше внимание), я использую VS2012 и, по сути, использую встроенные шаблоны для C #. В этом случае я создал тестовое приложение формы, использовал шаблон класса, а затем добавил приведенный выше код. Форма имеет простую кнопку «Выполнить все», которая запускает создание экземпляра класса и, следовательно, строк подпоследовательности, как показано ниже. Форма имеет текстовое поле для простого отображения результата.   -  person Robert Springer    schedule 03.11.2016
comment
Подпись для функции С++ - это то, что я не могу изменить. Он имеет тип BSTR** для второго параметра, который генерирует [in] для интерфейса.   -  person Robert Springer    schedule 03.11.2016
comment
который сгенерировал [in], странно задом наперед. Вы сначала пишете IDL, требуется [out,retval]. Затем он компилируется MIDL, и вы получаете файл .h, который вы включаете в свой код C++.   -  person Hans Passant    schedule 03.11.2016


Ответы (2)


В .idl интерфейс должен быть

HRESULT _stdcall CallMe([in] BSTR clientName, 
                        [out,retval] BSTR** helloMessage);

Так что просто возьмите возвращаемое значение из CallMe

SimpleChatServer mySimpleCom = new SimpleChatServer();   
string helloMessage = mySimpleCom( clientName );

Когда вы возвращаете строку в методе C++/C, вы выделяете ее с помощью SysAllocString и возвращаете ее вызывающей стороне, назначая helloMessage.

i.e.

*helloMessage = SysAllocString(L"MyString");

Все вышеизложенное предполагает, что вы ссылались на COM-сервер в своем проекте C#.

Теперь я более внимательно прочитал ваш вопрос, так что вы не можете изменить «устаревший» код? если он говорит

HRESULT _stdcall CallMe([in] BSTR clientName, 
                        [in] BSTR** helloMessage);

Тогда его следует изменить, потому что это неправильно.

person AndersK    schedule 03.11.2016
comment
ХЕ-ХЕ - Это то, что я понял, и я сообщил им об этом, они ответили, что это то, что есть. Итак, технически - и, как я думал, для того, чтобы я мог получить то, что они пытаются передать обратно во втором параметре, им нужно что-то исправить, чтобы он имел атрибут параметра [out, retval]. - person Robert Springer; 03.11.2016
comment
@RobertSpringer, по крайней мере, вы, вероятно, получите утечку памяти при вызове функции, если она останется как [in][in] - person AndersK; 03.11.2016

Спасибо всем и Андресу

Я, наконец, связался с клиентом, и да, предоставленная им информация была неверной, а атрибут [in] должен был быть [out,retval], чтобы разрешить передачу строки назад — как только они это исправили, все пошло нормально .

Всем большое спасибо-спасибо

person Robert Springer    schedule 10.11.2016