Управление форвардом из Си++

Здесь обсуждаются любые продукты компании СофтЛаб-НСК для телевизионного вещания (Форвард Т, Форвард ТС, Форвард Голкипер, Форвард Рефери, Форвард Офис, Форвард Инжест)

Модераторы: ElenVR, Людмила, PR

Ответить
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Управление форвардом из Си++

Сообщение int »

После изучения SDK касательно SLMessageServer, начал переводить пример, написанный на Borland C++ Builder на MS Visual C++.

Не удается пока сделать экземпляр класса ISLMSConnection. Проблема в переводе вот этой строки на Visual C++:

Код: Выделить всё

    // создать сервер для связи
    ResultCode=CoSLMSConnection::Create(Connection);
Переменные класса объявлены следующим образом:

Код: Выделить всё

	ISLMSConnection *Connection;
	ISLMSQueue *Queue;

	SLMSErrorCode ErrorCode;
	HRESULT ResultCode;
Поскольку опыта у меня с COM+/ActiveX не особо много, возникли вопросы:

1. Откуда префикс Co взялся? Фишка компилятора от Borland или самой технологии?
2. Решил сделать вот такую штуку:

Код: Выделить всё

		CLSID clsid;
		HRESULT hr = CLSIDFromProgID(L"SLMessageQueue2Lib.SLMSServer", &clsid);

		if(FAILED(hr)) {

			::MessageBoxW(NULL, L"CLSIDFromProgID() failed", L"Error", 0x10010);
			return 0;
		}
Получить CLSID не удается. Почему это может быть? Пробовал запускать как на машине с платой форвард, так и без нее.
3. Какая вообще суть в "CoSLMSConnection::Create"? Что происходит при выполнении хотя бы примерно? Чтение документации по COM не дало понимания, пробовал CoCreateInstance, но безрезультатно.

Вопросы, наверно, слишком глупые, но очень не хочется разбивать программу на два модуля, один из которых был бы на C# (пример из SDK), а другой на Visual C++/GCC с сокетами между ними.
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Поскольку опыта у меня с COM+/ActiveX не особо много
COM+/ActiveX для вызова SLMessageServer не нужно. Достаточно обычного COM.

Я при работе под MS Visual C++ для вызова SLMessageServer делаю примерно так:

1. В файл stdafx.h добавляются строки:

Код: Выделить всё

// SLMessageServer
#import "libid:80418EB6-3E79-4F86-AB75-9549D4F38BD8" named_guids raw_interfaces_only
Естественно, для работы этого импорта на машине должно быть установлено наше ПО и собственно SLMessageServer.

2. В классе описываю переменные:

Код: Выделить всё

CComPtr<SLMessageQueue2Lib&#58;&#58;ISLMSConnection> m_pConnection;
CComPtr<SLMessageQueue2Lib&#58;&#58;ISLMSQueue> m_pQueue;
Для возможности использования CComPtr нужно использовать ATL.

3. Там, где нужно создать экземпляр объекта:
m_pConnection.CoCreateInstance(SLMessageQueue2Lib::CLSID_SLMSConnection);
У меня это работает.

Дальше, в соответствии с SDK, создается очередь (объект m_pQueue) для приема-передачи сообщений.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Собралось, но падает:

First-chance exception at 0x7629c41f in forward_test.exe: 0x800706B5: Неизвестный интерфейс.

Падает именно при создании объекта.
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

First-chance exception - это еще не "падает". Это лишь программное исключение, но не фатальное, как access violation, например.

А если так попробовать?

Код: Выделить всё

CComPtr<IUnknown> m_pConnection;
m_pConnection.CoCreateInstance&#40;SLMessageQueue2Lib&#58;&#58;CLSID_SLMSConnection&#41;;
В запуске приложения COM не забыли инициализировать? В списке системных сервисов SLMessageServer2 присутствует? В каком состоянии - работает?

Сервисы можно посмотреть так: кнопка Пуск, в поле поиска набрать services.msc и нажать [Enter].
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

служба SLMessageServer2 работает

::CoInitialize(NULL); вызывается первым делом в int main()

ResultCode = m_pConnection.CoCreateInstance(SLMessageQueue2Lib::CLSID_SLMSConnection);

возвращает S_OK, но в логе Visual Studio показывается это исключение. Вы правы, это первое исключение. Но если программа продолжит выполнение, то вылетит с 0xC0000005 после return 0 в main функции. Ставить SEH пробовал - не помогает, просто не ловит исключение в обработчике.

Вот полный лог:

First-chance exception at 0x7629c41f in forward_test.exe: 0x800706B5: Неизвестный интерфейс.
'forward_test.exe': Unloaded 'C:\Program Files\Common Files\SoftLab-Nsk\SLMessageQueue2.dll'
'forward_test.exe': Unloaded 'C:\Windows\SysWOW64\ws2_32.dll'
'forward_test.exe': Unloaded 'C:\Windows\SysWOW64\nsi.dll'
First-chance exception at 0x01311ce5 in forward_test.exe: 0xC0000005: Access violation reading location 0x00d14ec0.
Unhandled exception at 0x77e515de in forward_test.exe: 0xC0000005: Access violation reading location 0x00d14ec0.

Менять тип интерфейса на IUnknown пробовал - без результатов.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Убрал CoUninitialize и падать перестало. Но теперь форвард игнорирует приходящие на него сообщения. Вот что в итоге получилось по коду:

Код: Выделить всё

#include "forward.h"
#include <atlbase.h>
#include <iostream>
#include <comutil.h>
#include <string>

class Sample &#123;
public&#58;
	SLMessageQueue2Lib&#58;&#58;SLMSErrorCode ErrorCode;
	HRESULT ResultCode;

	CComPtr<SLMessageQueue2Lib&#58;&#58;ISLMSConnection> m_pConnection;
	CComPtr<SLMessageQueue2Lib&#58;&#58;ISLMSQueue> m_pQueue;

	// Соединиться с сервером, создать очередь для приема сообщений, 
	// передать параметры для PostMessage по приходу сообщения
	bool Init
		&#40;
			BSTR QueueName,
			HWND NotifyWindow,
			long NotifyMessage,
			long NotifyWParam,
			long NotifyLParam
		&#41;
	&#123;
		// создать сервер для связи
		ResultCode = m_pConnection.CoCreateInstance&#40;SLMessageQueue2Lib&#58;&#58;CLSID_SLMSConnection&#41;;
		if &#40;ResultCode == S_FALSE&#41;
			return false;
		// создать очередь
		LPUNKNOWN ptr = 0;
		HRESULT res = m_pConnection->CreateQueue&#40;&ErrorCode, &ResultCode, QueueName,
			&#40;long&#41;NotifyWindow, NotifyMessage, NotifyWParam, NotifyLParam, &ptr&#41;;
		if &#40;res != S_OK&#41; &#123;
			ResultCode = res;
			return false;
		&#125;
		if &#40;ErrorCode != SLMessageQueue2Lib&#58;&#58;mcSuccess&#41; return false;
		ResultCode = ptr->QueryInterface&#40;SLMessageQueue2Lib&#58;&#58;IID_ISLMSQueue, &#40;void**&#41;&m_pQueue&#41;;
		ptr->Release&#40;&#41;;
		if &#40;ResultCode != S_OK&#41; return false;
		// готов к работе с сообщениями
		return true;
	&#125;

	// Послать сообщение.
	// Успех означает, что сообщение попало к локальному серверу.
	// В случае ошибки при дальнейшем прохождении в очередь вернется
	//  сообщение об ошибке c ReplyTo==ThisMessId
	bool SendMessage
		&#40;
			long ThisMessId,
			BSTR ToMachine,
			BSTR ToQueue,
			BSTR Subject,
			BSTR Body
		&#41;
	&#123;
		BSTR pc_name;
		m_pConnection->GetName&#40;&pc_name&#41;;
		char* CharStr = _com_util&#58;&#58;ConvertBSTRToString&#40;pc_name&#41;;
		if &#40;CharStr != NULL&#41;
		&#123;
			std&#58;&#58;string StdStr&#40;CharStr&#41;;
			std&#58;&#58;cout << StdStr << std&#58;&#58;endl;
			delete&#91;&#93; CharStr;
		&#125;
		HRESULT res = m_pQueue->SLSendMessage&#40;&ErrorCode, &ResultCode, ThisMessId, 0, 0,
			pc_name, ToQueue, Subject, Body&#41;;
		SysFreeString&#40;pc_name&#41;;
		CharStr = _com_util&#58;&#58;ConvertBSTRToString&#40;Subject&#41;;
		if &#40;CharStr != NULL&#41;
		&#123;
			std&#58;&#58;string StdStr&#40;CharStr&#41;;
			std&#58;&#58;cout << StdStr << std&#58;&#58;endl;
			delete&#91;&#93; CharStr;
		&#125;
		CharStr = _com_util&#58;&#58;ConvertBSTRToString&#40;ToQueue&#41;;
		if &#40;CharStr != NULL&#41;
		&#123;
			std&#58;&#58;string StdStr&#40;CharStr&#41;;
			std&#58;&#58;cout << StdStr << std&#58;&#58;endl;
			delete&#91;&#93; CharStr;
		&#125;
		CharStr = _com_util&#58;&#58;ConvertBSTRToString&#40;Body&#41;;
		if &#40;CharStr != NULL&#41;
		&#123;
			std&#58;&#58;string StdStr&#40;CharStr&#41;;
			std&#58;&#58;cout << StdStr << std&#58;&#58;endl;
			delete&#91;&#93; CharStr;
		&#125;
		if &#40;res != S_OK&#41; &#123;
			ResultCode = res;
			return false;
		
		&#125;
		if &#40;ErrorCode != SLMessageQueue2Lib&#58;&#58;mcSuccess&#41; return false;
		return true;
	&#125;

	// По получении определенного ранее оконного сообщения
	//  можно вычитать из очереди пришедшее сообщение
	void GetMessage&#40;&#41; &#123;
		SLMessageQueue2Lib&#58;&#58;SLMSMessageType MessType;
		long MessId, ReplyTo, SentLo, SentHi;
		BSTR FromMachine, FromQueue, Subject, Body;
		// получаем параметры сообщения
		HRESULT res = m_pQueue->SLGetMessage&#40;&ErrorCode, &ResultCode,
			&MessType, &MessId, &ReplyTo,
			&SentLo, &SentHi,
			&FromMachine, &FromQueue,
			&Subject, &Body&#41;;
		if &#40;res != S_OK || ErrorCode != SLMessageQueue2Lib&#58;&#58;mcSuccess&#41; &#123;
			// Сообщение не получено, ничего освобождать не надо
			return;
		&#125;
		// проверяем тип сообщения
		if &#40;MessType == SLMessageQueue2Lib&#58;&#58;mtError&#41; &#123;
			// Сообщение об ошибке
			//ВывестиКудато&#40;ErrorCode,ResultCode,ReplyTo&#41;;
		&#125; else if &#40;MessType == SLMessageQueue2Lib&#58;&#58;mtMessage&#41; &#123;
			// Сообщение от кого-то
			//ОбработатьСообщение&#40;FromMachine,FromQueue,Subject,Body&#41;;
		&#125; else &#123;
			// Служебное сообщение
		&#125;
		// обязательно освободить полученные от сервера строки
		SysFreeString&#40;FromMachine&#41;;
		SysFreeString&#40;FromQueue&#41;;
		SysFreeString&#40;Subject&#41;;
		SysFreeString&#40;Body&#41;;
	&#125;

&#125;;

int main&#40;&#41; &#123;
	//
	HRESULT hRes = &#58;&#58;CoInitialize&#40;NULL&#41;;
	if &#40;hRes != S_OK&#41;
		return 0;
	Sample test;
	BSTR queue_name = SysAllocString&#40;L"FDOnAir1"&#41;;
	BSTR subject = SysAllocString&#40;L"OnAir1.Mirror"&#41;;
	BSTR cmd = SysAllocString&#40;L"Shedule.Start"&#41;;
	if &#40;test.Init&#40;queue_name, NULL, 0, 0, 0&#41;&#41;
		test.SendMessage&#40;0, L"", queue_name, subject, cmd&#41;;
	//&#58;&#58;CoUninitialize&#40;&#41;;
	SysFreeString&#40;queue_name&#41;;
	SysFreeString&#40;subject&#41;;
	SysFreeString&#40;cmd&#41;;

	return 0;
&#125;
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Во-первых, вместо BSTR пользуйтесь классом CComBSTR, тогда ничего и освобождать не придется. Только конвертировать строку в CComBSTR нужно непосредственно перед вызовом COM-объекта, и это делается просто конструктором CComBSTR.

Во-вторых, для работы со строками используйте класс CString (если не компилируется, добавьте #include <atlstr.h> в stdafx.h). И никаких delete не потребуется. В параметры процедур передавайте CString, а не BSTR.

В-третьих, для посылки на локальную машину в pc_name нужно явно указывать строку "localhost", а не пустую строку.

Как-то так:

Код: Выделить всё

bool SendMessage&#40;long ThisMessId, 
  CString ToQueue, CString Subject, CString Body&#41; 
   &#123; 
      CComBSTR pc_name&#40;L"localhost"&#41;;
      CComBSTR bQueue&#40;ToQueue&#41;,bSubject&#40;Subject&#41;,bBody&#40;Body&#41;;
      HRESULT res = m_pQueue->SLSendMessage&#40;&ErrorCode, &ResultCode, ThisMessId, 0, 0, 
         pc_name, bQueue, bSubject, bBody&#41;;
Прием сообщений - отдельная песня, их нужно через окно принимать, вы сначала с посылкой разберитесь.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

По поводу третьего пункта не соглашусь, пустая строка в параметрах это просто атавизм. Там же написано:

BSTR pc_name;
m_pConnection->GetName(&pc_name);

И на консоль уходит ровно то, что стоит в SLMessageSample_C# в поле ввода "Computer:".

По поводу CString попробую, но не думаю, что это что-то изменит. Через SLMessageSample_C# получается нажать "Старт ->" (Shedule.Start), а самому из своего проекта - нет. При этом все параметры одинаковые. В любом случае, спасибо за помощь! Буду копать дальше.
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Как хотите - у меня со строкой "localhost" работает. У вас - пока не работает, не так ли?
При этом все параметры одинаковые.
У меня нет уверенности в том, что все параметры на 100% одинаковые. Я бы попробовал в тестовом примере поставить точку останова непосредственно перед вызовом посылки сообщения, и посмотреть значения всех параметров. Потом поставить точку останова в вашей программе и посмотреть, что все параметры имеют в точности такие же значения. Если не работает, значит, какие-то параметры в вызовах все-таки отличаются. Чудес не бывает.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Чудес не бывает, но все же использование SLMessageServer из C# (т.е. через .NET) и C++ (нативный код, Win API и COM) отличаются.

Приведу пример. Открываю forward_test.exe, получаю следующий лог на экран:

prepare connection...
connected!
queue created!
interface checked!
pc_name: STUDIO-AR-1, queue: FDOnAir1, subject: OnAir1.Mirror, body: Shedule.Start

Открываю следом Forward OnAir, наличие зацепленного приложения ему не нравится:

Ошибка

SLMSConnection::CreateQueue "FDOnAir1" failed
SKMS ErrorCode: mcUnknown
HRESULT: AOI error 0 16389: Неопознанная ошибка

Закрываю forward_test.exe, закрываю OnAir.

Теперь следующий эксперимент. Открываю OnAir, запускаю программу forward_test.exe. Результат не менее интересный:

prepare connection...
connected!
Init failed!

Ничего подобного с примером из SDK сделать не удавалось. Ну максимум службу перезапускаешь у него хендл отваливается, оно и понятно, Release/Create эту проблему лечит. Но запускать это приложение можно даже до запуска OnAir (с подключением к очереди, так и без этого) и тот не ругается.

Полный текст программы на текущий момент представлен ниже:

Код: Выделить всё

#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
#include <comutil.h>
#include <string>
#include <comutil.h>

#import "libid&#58;80418EB6-3E79-4F86-AB75-9549D4F38BD8" named_guids raw_interfaces_only\
	rename&#40;"GetMessage", "SLGetMessage"&#41;\
	rename&#40;"SendMessage", "SLSendMessage"&#41;

std&#58;&#58;string convert&#40;BSTR input&#41; &#123;
	std&#58;&#58;string res&#40;_com_util&#58;&#58;ConvertBSTRToString&#40;input&#41;&#41;;
	return res;
&#125;

class Sample &#123;
private&#58;
	static const int _notifyCmd;
public&#58;
	SLMessageQueue2Lib&#58;&#58;SLMSErrorCode ErrorCode;
	HRESULT ResultCode;

	CComPtr<SLMessageQueue2Lib&#58;&#58;ISLMSConnection> m_pConnection;
	CComPtr<SLMessageQueue2Lib&#58;&#58;ISLMSQueue> m_pQueue;

	BSTR real_pc_name;

	long ThisMessId;
	// Соединиться с сервером, создать очередь для приема сообщений, 
	// передать параметры для PostMessage по приходу сообщения
	bool Init
		&#40;
			CString QueueName
		&#41;
	&#123;
		// создать сервер для связи
		ResultCode = m_pConnection.CoCreateInstance&#40;SLMessageQueue2Lib&#58;&#58;CLSID_SLMSConnection&#41;;
		if &#40;ResultCode == S_FALSE&#41;
			return false;
		std&#58;&#58;cout << "connected!" << std&#58;&#58;endl;
		// создать очередь
		LPUNKNOWN ptr = 0;
		CComBSTR bQueueName&#40;QueueName&#41;;
		HRESULT res = m_pConnection->CreateQueue&#40;&ErrorCode, &ResultCode, bQueueName,
			NULL, 0, 0, 0, &ptr&#41;;
		if &#40;res != S_OK&#41; &#123;
			ResultCode = res;
			return false;
		&#125;
		if &#40;ErrorCode != SLMessageQueue2Lib&#58;&#58;mcSuccess&#41; return false;
		std&#58;&#58;cout << "queue created!" << std&#58;&#58;endl;
		ResultCode = ptr->QueryInterface&#40;SLMessageQueue2Lib&#58;&#58;IID_ISLMSQueue, &#40;void**&#41;&m_pQueue&#41;;
		ptr->Release&#40;&#41;;
		if &#40;ResultCode != S_OK&#41; return false;
		std&#58;&#58;cout << "interface checked!" << std&#58;&#58;endl;
		m_pConnection->GetName&#40;&real_pc_name&#41;;
		ThisMessId = 0;
		// готов к работе с сообщениями
		return true;
	&#125;

	// Послать сообщение.
	// Успех означает, что сообщение попало к локальному серверу.
	// В случае ошибки при дальнейшем прохождении в очередь вернется
	//  сообщение об ошибке c ReplyTo==ThisMessId
	bool FDSendMessage&#40;CString ToQueue, CString Subject, CString Body&#41; 
	&#123;
		//CComBSTR pc_name&#40;L"localhost"&#41;; 
		CComBSTR bQueue&#40;ToQueue&#41;, bSubject&#40;Subject&#41;, bBody&#40;Body&#41;; 
		HRESULT res = m_pQueue->SLSendMessage&#40;&ErrorCode, &ResultCode, ThisMessId++, 0, 0, 
			real_pc_name, bQueue, bSubject, bBody&#41;;
		// check result
		if &#40;res != S_OK&#41; &#123;
			ResultCode = res;
			std&#58;&#58;cout << "hRes " << res << std&#58;&#58;endl;
			return false;
		&#125;
		if &#40;ErrorCode != SLMessageQueue2Lib&#58;&#58;mcSuccess&#41; &#123;
			std&#58;&#58;cout << "errCode " << ErrorCode << std&#58;&#58;endl;
			return false;
		&#125;
		std&#58;&#58;cout << "pc_name&#58; " << convert&#40;real_pc_name&#41; <<
			", queue&#58; " << convert&#40;bQueue.m_str&#41; <<
			", subject&#58; " << convert&#40;bSubject.m_str&#41; <<
			", body&#58; " << convert&#40;bBody.m_str&#41; << std&#58;&#58;endl;
		return true;
	&#125;
&#125;;
const int Sample&#58;&#58;_notifyCmd = WM_USER + 200;

int main&#40;&#41; &#123;
	HRESULT hRes = &#58;&#58;CoInitialize&#40;NULL&#41;;
	if &#40;hRes != S_OK&#41;
		return 0;
	&#123;
		Sample test;
		CString queue_name = L"FDOnAir1";
		CString subject = L"OnAir1.Mirror";
		CString cmd = L"Shedule.Start";
		std&#58;&#58;cout << "prepare connection..." << std&#58;&#58;endl;
		if &#40;test.Init&#40;queue_name&#41;&#41; &#123;
			std&#58;&#58;string foo;
			do &#123;
				test.FDSendMessage&#40;queue_name, subject, cmd&#41;;
				std&#58;&#58;cin >> foo;
			&#125; while &#40;foo != "q"&#41;;
		&#125; else &#123;
			std&#58;&#58;cout << "Init failed!" << std&#58;&#58;endl;
		&#125;
	&#125;
	&#58;&#58;CoUninitialize&#40;&#41;;

	return 0;
&#125;
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

использование SLMessageServer из C# (т.е. через .NET) и C++ (нативный код, Win API и COM) отличаются
Использование отличается только с точки зрения синтаксиса языка, описания переменных и типов данных. Значения параметров в любом случае одинаковы. SLMessageServer "не знает", из какой программы его вызывают - написанной на C++, C# или Delphi. Это - COM-объект, которому всё равно, откуда его вызывают. Только вызывают либо правильно, либо нет, другой причины быть не может. Важны только значения параметров, а не язык, на котором написан вызывающий клиент. Это основа идеологии COM.
наличие зацепленного приложения ему не нравится
То, что происходит, объясняется просто. FDOnAir при запуске создает очередь с названием "FDOnAir1". Когда тестовая программа пытается создать очередь с таким же названием, SLMessageServer обнаруживает, что такая же очередь уже есть, и не позволяет ее создать, возвращая ошибку. Не допускается существование двух очередей с одинаковым названием.

Соответственно, если сначала запустить тест, он создает очередь с именем "FDOnAir1", после чего запускаемый позже FDOnAir не может создать очередь с таким же названием, и ругается.

Ваше приложение должно создавать очередь не с названием "FDOnAir1", а любым другим. Например, "MyTestQueue". Поскольку вы хотите из очереди только посылать сообщения, а ничего принимать не нужно, название очереди - чистая формальность, лишь бы уже не было в системе очереди с таким названием.

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

Если опять не получится, пишите.
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Ступил, очереди и были основной ошибкой. Падение c CoUninitialize было вызвано тем, что вызывалось вместе с использованием COM объекта из main функции (фигурные скобки поставил для решения этой проблемы).

Еще раз спасибо за помощь! :)
vd
Сообщения: 2311
Зарегистрирован: 05 мар 2003 19:21

Сообщение vd »

Так заработало или нет? :-) Посылаются сообщения в OnAir?
Ступил, очереди и были основной ошибкой
Если честно, наш SDK по SLMessageServer не отличается особой ясностью изложения. Я его изучал несколько лет назад, тогда разобрался (с помощью автора сервера, поскольку он работает в соседней комнате), и еще тогда какие-то правки в SDK вроде вносил, т.к. многие моменты вовсе не очевидны. Погляжу документ еще раз и проверю, что там еще можно улучшить, чтобы стало понятнее.

P.S. CoUninitialize можно вообще не вызывать. Само вызовется при завершении работы программы.

P.P.S. Все-таки, чтобы не писать такие жуткие конструкции

Код: Выделить всё

std&#58;&#58;string convert&#40;BSTR input&#41; &#123; 
   std&#58;&#58;string res&#40;_com_util&#58;&#58;ConvertBSTRToString&#40;input&#41;&#41;; 
   return res; 
&#125;
проще, ИМХО, использовать CString и CComBSTR. Можно хоть туда, хоть обратно преобразовывать, без всяких Convert и в одну строку:

Код: Выделить всё

CString str&#40;_T&#40;"abc"&#41;&#41;;
CComBSTR bstr&#40;str&#41;;
CString str2&#40;bstr&#41;;
При этом, можно не задумываться о Unicode или Multi-byte строках - конструкторы классов "всеядные". Если нужно явно получить ANSI-строку, есть еще класс CStringA. Также не нужно задумываться о выделении/освобождении памяти - при использовании BSTR это очень важно, и можно легко понаделать ошибок. CComBSTR всё это автоматически реализует (работу с памятью). Не забывайте, что BSTR-строка передает данные через COM в другое приложение, нужно быть очень аккуратным, и можно легко нарваться на утечки памяти, вплоть до "взрыва" программы (access violation).
int
Сообщения: 21
Зарегистрирован: 03 июн 2013 14:12

Сообщение int »

Да, заработало.

В принципе GetMessage не так интересен. Во-первых у меня нет окна. А во-вторых основная задача по Forward - тормозить видео ролики и переключать расписание на видео вход, а там уже цепляется стэк микшеров, которые тоже управляются через сеть или COM-порты. Т.е. Forward настраивается отдельно и никакая информация из него не нужна. Максимум что может потребоваться - включить/выключить титровальные объекты (хотя это уже настроено в расписании). А так одной "Shedule.Start" уже достаточно. Сейчас это делает режиссер по заранее известному сценарию эфира. Поэтому возникла задача автоматизации.

convert тестовая игрушка которая из проекта будет выброшена. Нужна была только для вывода строк на stdout.
Погляжу документ еще раз и проверю, что там еще можно улучшить, чтобы стало понятнее.
На мой взгляд просто не хватает для альтернативы примера на Visual C++. Все-таки Borland C++ редко кем используется сейчас. Просто во многих SDK идут примеры сразу на нескольких языках, в смысле сами проекты, готовые к сборке. А по тексту SDK все было достаточно понятно. И неплохо бы в документации в примечаниях обозначить, что при создании очереди, ее имя должно быть уникальным. Т.е. объяснить момент, что каждая сторона создает свою очередь и они односторонние. И еще чего мне не хватало для понимания - информацию о регистрации SLMessageServer на машине БЕЗ платы Forward. При установке ForwardTxLite сервер сам не зарегистрировался и не был доступен. Эту информацию я уже вытягивал на форуме.
Даниленко Сергей
Сообщения: 7093
Зарегистрирован: 26 фев 2004 09:53
Откуда: Techsupport SoftLab-NSK

Сообщение Даниленко Сергей »

На мой взгляд просто не хватает для альтернативы примера на Visual C++. Все-таки Borland C++ редко кем используется сейчас. Просто во многих SDK идут примеры сразу на нескольких языках, в смысле сами проекты, готовые к сборке.
Да, не хватает. Просто разработчик, который писал данный раздел SDK - большой любитель борланда в то время был :(
Постараемся в дальнейшем что-нибудь придумать.
При установке ForwardTxLite сервер сам не зарегистрировался и не был доступен.
Сам не зарегистировался - это сбой. Но, вполне вероятно, что проблема была в чём-то другом. Например, мы недавно разбирались с проблемой когда сервис был зарегистрирован, но объекты SLMessageServer в сторонних приложениях не создавались.
Уверяю вас, что в обычной жизни SLMessageServer инсталлятором Forward Lite ставится без каких-либо проблем.
Ответить