GXDN: Gurux Developer Network
Gurux GXDevice component
In this walkthrough, you learn how to use Gurux GXDevice components (GXDevice) in the Visual C++ environment (C++ from now on). GXDeviceSample demonstrates how GXDevice is used in C++.
Adding GXDevice support to the project
  1. Start Visual C++
  2. Open the project where you want to add the GXDevice component, or create a new one
  3. Select Options in the Tools menu
  4. Select Directories tab and change "Show directories" to "Executable files"
  5. Add new directory to Directories list. New path is C:\Program Files\Common Files\Gurux\GXCom

Select StdAfx.h file and add following line to the bottom of the file.
#include <atlbase.h>
#import "GuruxClient.dll" raw_interfaces_only
#import "GuruxDevice.dll" raw_interfaces_only
using namespace GuruxClient;
using namespace GuruxDevice;
#include <afxctl.h> // Needed for AfxConnectionAdvise

Now Gurux Components are ready to be used from C++.
Creating components from C++
Before component can be used in C++, it must be created as follows.
CComPtr<IGXClient> GXClient1; 
// Create Media Component 
HRESULT hr = ::CoCreateInstance(__uuidof(GXClient), 0, CLSCTX_INPROC_SERVER, 
    __uuidof(IGXClient), (void**) GXClient1); 

///////////////////////////////////////////////////////////// 
// Establish a connection between source and sink.
// m_dwCookie is a cookie identifying the connection, and is needed 
// to terminate the connection.
LPUNKNOWN pUnk = GetIDispatch(FALSE); 
if (!AfxConnectionAdvise(GXClient1, __uuidof(_IGXDeviceEvents), pUnk, FALSE, &m_dwCookie))
{ 
    // Error.
    MessageBox("AfxConnectionAdvise Failed", "Gurux Media Sample", MB_OK | MB_ICONSTOP); 
    return FALSE;
}

Selecting media
First select used media and set media settings.
//Select new Media
hr = GXClient1->SelectMedia("Net");
hr = GXClient1->GetCurrentMedia(&GXNet1);
//Set server port and TCP/IP address
GXNet1->put_HostName(L"Localhost");
GXNet1->put_HostPort(1234);
//Assign new Media
hr = GXClient1->AssignMedia(GXClient1);

Changing properties
After Media is selected, set Protocol properties. You can either select appropriate settings in Properties dialog, or the settings can be changed programmatically.
//Set Protocol settings.
hr = GXClient1->put_HeaderSize(0);
//Make Error check
hr = GXClient1->put_DataSize(0);
//Make Error check 
hr = GXClient1->SetBOP("01", GX_VT_BYTE);
//Make Error check 
hr = GXClient1->SetEOP("02", GX_VT_BYTE);
//Make Error check
//OR
hr = GXClient1->Properties();
//Make Error check

Sending and receiving packets
Data can be sent synchronously or asynchronously. If data is sent synchronously, sent packet is filled with received packet's content. If packet is sent asynchronously, the response is received through __IGXDeviceEvents.Received event message.
Receiving event messages
To receive event messages, notify interface must be created. Add following code to header file where notify interface is implemented.
//Add support for GXMedia component notifies
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()

Add following code to the .cpp file where notify interface is implemented.
//Add support for GXMedia component notifies
BEGIN_INTERFACE_MAP(CGXDeviceSampleDlg, CDialog)
    INTERFACE_PART(CGXDeviceSampleDlg, __uuidof(_IGXDeviceEvents), Dispatch)
END_INTERFACE_MAP()
BEGIN_DISPATCH_MAP(CGXDeviceSampleDlg, CCmdTarget)
    DISP_FUNCTION_ID(CGXDeviceSampleDlg, "OnReceived", 5, OnReceived, VT_EMPTY, VTS_UNKNOWN VTS_BOOL)
    DISP_FUNCTION_ID(CGXDeviceSampleDlg, "OnError", 7, OnError, VT_EMPTY, VTS_WBSTR) 
END_DISPATCH_MAP()

/////////////////////////////////////////////////////////////////////////////
// Handle received data
/////////////////////////////////////////////////////////////////////////////
HRESULT CGXDeviceSampleDlg::OnReceived(VARIANT* Data, BSTR SenderInfo)
{
    // Get Data size
    long lSize = 0;
    if(FAILED(SafeArrayGetUBound(Data->parray, 1, &lSize)))
    {
        return S_OK;
    }
    CComVariant data;
    for (long pos = 0; pos < lSize; pos++)
    {
        if (FAILED(SafeArrayGetElement(Data->parray, &pos, &data)))
        {
            return S_OK;
        }
        m_dataReceived += data.bVal;
    }
    m_sender = SenderInfo;
    UpdateData(FALSE);
    return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// Show occurred error
/////////////////////////////////////////////////////////////////////////////
HRESULT CGXDeviceSampleDlg::OnError(BSTR ErrorInfo)
{
    USES_CONVERSION;
    MessageBox(W2T(ErrorInfo), "Gurux Media Sample", MB_OK | MB_ICONERROR);
    return S_OK;
}

Error Handling
It's very important to consider error handling when sending and receiving data. The connection can drop down, or something else unexpected may happen. If something unwanted happens, GXDevice returns error. The following example shows how to handle errors in C++.
////////////////////////////////////////////////////////////////////////////////
// This method helps you to see in text form what error GXDevice returned.
////////////////////////////////////////////////////////////////////////////////
CString GetGXError(IUnknown* pUnknown)
{
    CString errStr;
    if (pUnknown == NULL)
    {
        return errStr;
    }
    CComPtr<ISupportErrorInfo> pSupportErrorInfo = NULL;
    CComPtr<IErrorInfo> pErrorInfo = NULL;
    HRESULT hr = pUnknown->QueryInterface(IID_ISupportErrorInfo, (void**) &pSupportErrorInfo);
    if (FAILED(hr))
    {
        return errStr;
    }
    
    //If interface doesn't support error info don't go further.
    if (FAILED(pSupportErrorInfo->InterfaceSupportsErrorInfo(IID_IUnknown)))
    {
        return errStr;
    }
    
    // Get the current error object. Return if no error object exists.
    GetErrorInfo(0,&pErrorInfo);
    if (pErrorInfo == NULL) 
    {
        return errStr;
    }
            
    //Get error description
    CComBSTR err;
    pErrorInfo->GetDescription(&err);
    errStr = err;
    return errStr;
}

//////////////////////////////////////////////////////////////////////////////// 
// Create Media Components
////////////////////////////////////////////////////////////////////////////////
void CreateComponents()
{
    if(FAILED(::CoCreateInstance(__uuidof(GXClient), 0,
            CLSCTX_INPROC_SERVER,
            __uuidof(IGXClient),
            (void**) &m_GXClient1)))
    {
        //Show Error if any
        MessageBox(GetGXError(m_GXClient1), "Gurux Media Sample", MB_OK | MB_ICONERROR);
    }

    ///////////////////////////////////////////////////////////// 
    //Establish a connection between source and sink. 
    //m_dwCookie is a cookie identifying the connection, and is needed 
    //to terminate the connection. 
    LPUNKNOWN pUnk = GetIDispatch(FALSE); 
    if (!AfxConnectionAdvise(m_GXClient1, __uuidof(_IGXDeviceEvents), pUnk, FALSE, &m_dwCookie)) 
    {
        // Error. MessageBox("AfxConnectionAdvise Failed", "Gurux Media Sample", MB_OK | MB_ICONSTOP);
        return FALSE; 
    }
}

//////////////////////////////////////////////////////////////////////////////// 
// Close Media Components
////////////////////////////////////////////////////////////////////////////////
void CloseComponents()
{
    LPUNKNOWN pUnk = GetIDispatch(FALSE); 
    /////////////////////////////////////////////////////////////
    //Release sink. 
    //Terminate a connection between source and sink. 
    //m_pUnkSrc is IUnknown of server obtained by CoCreateInstance(). 
    //m_dwCookie is a value obtained through AfxConnectionAdvise(). 
    if (!AfxConnectionUnadvise(m_GXClient1 , __uuidof(_IGXDeviceEvents), pUnk, FALSE, m_dwCookie)) 
    {
        // Error. 
        MessageBox("AfxConnectionAdvise Failed", "CPP Sample", MB_OK | MB_ICONSTOP); 
    } 
            
    //Release Components when application is closing. 
    m_GXClient1 = NULL; 
    CoUninitialize(); 
}

Using the components from development environment

Using from .NET | Using from Visual Basic | Using from C++ | Note on parameter types