I have given it a try. Here is what I did:
The project that builds well (and it actually also runs) is the DumpAddressSpace. Here is the relevant code:
// $Header: $
// Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved.
// DumpAddressSpace.cpp : Defines the entry point for the console application.
// Dumps OPC server's address space recursively to the console.
//
#include "stdafx.h"
#import "libid:FAB7A1E3-3B79-4292-9C3A-DF39A6F65EC1" version(5.2) // EasyOpcLib
#import "scrrun.dll" rename("DeleteFile", "DeleteFileX") rename("MoveFile", "MoveFileX") rename("CopyFile", "CopyFileX") \
exclude("IDrive", "IDriveCollection", "IFileSystem", "IFileSystem3", "IFolder", "ITextStream", "IFolderCollection", "IFile", \
"IFileCollection")
using namespace EasyOpcLib;
using namespace Scripting;
//
void DumpBranch(IEasyDAClientPtr EasyDAClientPtr, LPCTSTR ParentItemId, int Level)
{
// Browse all nodes (branches and leaves) under ParentItemId
IDictionaryPtr NodeElementDictionaryPtr(EasyDAClientPtr->BrowseNodes(_T(""), _T("OPCLabs.KitServer.2"), ParentItemId));
variant_t vKeys(NodeElementDictionaryPtr->Keys());
variant_t vItems(NodeElementDictionaryPtr->Items());
LONG Ubound;
SafeArrayGetUBound(vKeys.parray, 1, &Ubound);
for (LONG i = 0; i <= Ubound; i++)
{
_variant_t vKey;
SafeArrayGetElement(vKeys.parray, &i, &vKey);
_variant_t vItem;
SafeArrayGetElement(vItems.parray, &i, &vItem);
IDANodeElementPtr NodeElementPtr(vItem);
for (int j = 0; j < Level; j++) _tprintf(_T(" "));
_tprintf(_T("'%s': HasChildren %d, IsBranch %d, IsLeaf %d, ItemId '%s', Name '%s'\n"),
(TCHAR*)_bstr_t(vKey),
NodeElementPtr->HasChildren,
NodeElementPtr->IsBranch,
NodeElementPtr->IsLeaf,
(TCHAR*)NodeElementPtr->ItemId,
(TCHAR*)NodeElementPtr->Name);
// If this node is a branch, dump its children recursively
if (NodeElementPtr->IsBranch)
DumpBranch(EasyDAClientPtr, NodeElementPtr->ItemId, Level + 1);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// Initialize the COM library
CoInitialize(NULL);
// Instatiate the EasyOPC-DA client object
IEasyDAClientPtr EasyDAClientPtr(__uuidof(EasyDAClient));
// Dump the OPC address space from the root branch
DumpBranch(EasyDAClientPtr, _T(""), 0);
// Release all interface pointers BEFORE calling CoUninitialize()
EasyDAClientPtr = NULL;
CoUninitialize();
TCHAR line[80];
_putts(_T("Press Enter to continue..."));
_fgetts(line, sizeof(line), stdin);
return 0;
}
This project uses what is called I think "native compiler support" for COM, i.e. it has its own version of smart pointer classes etc. (different from ATL or COM), and it is capable of "importing" the type library and creating the C++ definitions of interfaces and classes.
This approach should work pretty well as long as you are just calling methods. It will probably get a bit complicated or problematic once you need to set up events (for notifications - subscriptions).
Let me know if you need more help in this area, such as providing example for reading, writing etc.