• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

C++ and 64 bit COM

Started by James C. Fuller, October 29, 2013, 02:36:19 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

James C. Fuller

Patrice,
  Have you investigated 64bit COM ? Not creation of objects but connecting to 64bit COM objects from a 64bit Unicode app.

Maybe José or Fred could chime in here and add their expertise.

Is COM being phased out or is it still active as ever in Win8?

James

José Roca

I haven't tried anything 64-bit related yet.

Far from being phased, winRT is all COM.

Patrice Terrier

QuoteHave you investigated 64bit COM ?
No, i must first complete the translation of my graphic LIBs, before i can play with it.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

Despite being declared "dead" several times, COM is alive and well in Windows and will continue to be. The technology is a core part of the operating system, desktop and RT platforms alike, and isn't going anywhere. With regards to COM as a preferred interface for third-party components (e.g.: ActiveX controls), their use has declined simply because of the switch to .NET. Although not authoritative, a quick search on ComponentSource lists over 1,500 products that include commercial .NET components and under 500 products with ActiveX/COM components. And of those products with COM components, it only looks like 60 or so are 64-bit.

So COM as an operating system technology is here to stay. As a technology for reusable components by third-party vendors, it's still in use but not nearly as widespread as it used to be.
Mike Stefanik
sockettools.com

José Roca

While I never have been much interested in using ActiveX controls (excepting the Web Browser control), I began to learn COM programming when I discovered that about two thirds of the operating system and Microsoft technologies were implemented as low-level COM servers. M$ uses C++ classes to write wrappers, but when it comes to core technologies, it uses COM. It is not only more secure, but it is a binary standard, meaning that most languages can use it.

James C. Fuller

While not exactly what I was looking for I found among the archives COM creation source that will translate and compile to 64bit with VS12.

James
bc9Basic code:

'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
'
'=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
$CPPHDR
$NOMAIN
$ONEXIT "ULEX.EXE $FILE$.CPP TCHARXLATER_VC.TXT"
$ONEXIT "VS12.BAT $FILE$ -m64 con"
$HEADER
#include "objbase.h"
$HEADER

'-------------------------
' interface definition
'-------------------------
Interface IComponent Using IUnknown
    public:
        Dim    Function _Print (msg As const char ptr)=0 As void virtual STDCALL
End Interface

'-----------------------------------------------//
'Interface identifier, which is a 128-bit value.//
'-----------------------------------------------//
static As const IID IID_IComponent = { 0x853b4626, 0x393a, 0x44df, _
                                     { 0xb1, 0x3e, 0x64, 0xca, 0xbe, 0x53, 0x5d, 0xbf } }
'-------------------------
'Components class definition
'-------------------------
Class CComponent Using public IComponent
    public:
        '// IUnknown implementation
        Dim Function QueryInterface( iid As const IID&, ppv As void Ptr Ptr) As HRESULT virtual STDCALL
        Dim Function AddRef() As ULONG virtual STDCALL
        Dim Function Release() As ULONG virtual STDCALL
       
        '// Interface IComponent implementation
        Dim Function _Print(msg As const char ptr) As void virtual STDCALL
        Dim Constructor CComponent()
        Dim Destructor ~CComponent()
    private:
        Raw As long m_cRef    'the reference count   
End Class

'QueryInterface implementation
Function CComponent::QueryInterface(iid As const IID&,ppv As void Ptr Ptr) As HRESULT STDCALL
'If quering the IUnknown interface,return a pointer to IUnknown interface.     
    If iid = IID_IUnknown Then   
        _Print("Returning pointer to IUnknown...")
        *ppv = static_cast<IComponent*>(this)
'If quering the IComponent interface,return a pointer to IComponent interface.
    ElseIf iid = IID_IComponent Then
        _Print("Returning pointer to IComponent interface...")
        *ppv=static_cast<IComponent*>(this)
    Else
        _Print("Interface is not supported!.")
        *ppv = NULL
        Function = E_NOINTERFACE
    End If     
    'The reinterpret_cast operator allows any pointer to be converted into
    'any other pointer type.
    reinterpret_cast<IUnknown*>(*ppv)->AddRef()
   
    Function = S_OK
End Function
'------------------------------------------------------------------------------
Function CComponent::AddRef() As ULONG STDCALL
    _Print("Incrementing the referance count variable...")
    Function = InterlockedIncrement(&m_cRef)
End Function
Function CComponent::Release() As ULONG STDCALL
    _Print("Decrementing the referance count variable...")
    If InterlockedDecrement(&m_cRef)= 0 Then
        delete this
        Function = 0
    End If
    Function = m_cRef   
End Function
'------------------------------------------------------------------------------
$IPRINT_OFF
Sub CComponent::_Print(msg As const char Ptr)
    'cout<<"-----------------------"<<endl
    cout <<" Component:\t" << msg << endl
    'cout<<"-----------------------"<<endl
End Sub
$IPRINT_ON
'------------------------------------------------------------------------------
Constructor CComponent::CComponent()
     _Print("Constructing the component...")
     m_cRef=0;
End Constructor
'------------------------------------------------------------------------------
Destructor CComponent::~CComponent()
    _Print("Destructing the component...")
End Destructor
'==============================================================================
Function CreateInstance() As IUnknown Ptr
    Raw As IUnknown Ptr pIUnknown = (new CComponent)
    Function = pIUnknown
End Function

Function main() As Integer
    Raw As IUnknown Ptr pIUnknown = CreateInstance()
    Raw As IComponent Ptr pIComponent=NULL
    pIUnknown->QueryInterface(IID_IComponent,(void**)&pIComponent)
    pIComponent->_Print("COM from scratch")
    pIComponent->Release()
    Pause
End Function



C++ code:
// *********************************************************************
//  Created with bc9Basic - BASIC To C/C++ Translator (V) 9.1.6.9 (2013/10/30)
//       The bc9Basic translator (bc9.exe) was compiled with
//       Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86
// ----------------------------------------------------------------------
//                 BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
//              Translated for compiling with a C++ Compiler
//                           On MS Windows
// *********************************************************************
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif
// Additional lines may be needed
#if defined( __cplusplus )
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <locale>
#include <algorithm>
#include <vector>
typedef std::string::value_type charT;
typedef std::string stdstr;
#define _X(y) y
using namespace std;
#endif
#include <windows.h>    // Win32 Header File
#include <windowsx.h>   // Win32 Header File
#include <commctrl.h>   // Win32 Header File
#include <commdlg.h>    // Win32 Header File
#include <mmsystem.h>   // Win32 Header File
#include <shellapi.h>   // Win32 Header File
#include <shlobj.h>     // Win32 Header File
#include <objbase.h>    // Win32 Header File
#include <ocidl.h>      // Win32 Header File
#include <winuser.h>    // Win32 Header File
#include <olectl.h>     // Win32 Header File
#include <oaidl.h>      // Win32 Header File
#include <ole2.h>       // Win32 Header File
#include <oleauto.h>    // Win32 Header File
#include <winsock.h>    // Win32 Header File
#include <wchar.h>      // dos/linux
#include <ctype.h>      // dos/linux
#include <fcntl.h>      // dos/linux
#include <math.h>       // dos/linux
#include <stdio.h>      // dos/linux
#include <string.h>     // dos/linux
#include <stdlib.h>     // dos/linux
#include <setjmp.h>     // dos/linux
#include <stdarg.h>     // dos/linux
#include <sys/types.h>
#include <sys/stat.h>
#include <tchar.h>
#include <wctype.h>
#define uni_gets(A) _fgetts(A,1024,stdin)
//<---UNICODE AWARE
#define scout cout
//>---UNICODE AWARE


// ***************************************************
// Compiler Defines
// ***************************************************

// C++
#if defined( __cplusplus )
#define overloaded
#define C_EXPORT EXTERN_C __declspec(dllexport)
#define C_IMPORT EXTERN_C __declspec(dllimport)
#else
#define C_EXPORT __declspec(dllexport)
#define C_IMPORT __declspec(dllimport)
#endif


// Microsoft VC++
#ifndef DECLSPEC_UUID
#if (_MSC_VER >= 1100) && defined ( __cplusplus )
#define DECLSPEC_UUID(x)    __declspec(uuid(x))
#else
#define DECLSPEC_UUID(x)
#endif
#endif

// ***************************************************

#include "objbase.h"


// *************************************************
// Instruct Linker to Search Object/Import Libraries
// *************************************************
#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"user32.lib")
#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"advapi32.lib")
#pragma comment(lib,"winspool.lib")
#pragma comment(lib,"shell32.lib")
#pragma comment(lib,"ole32.lib")
#pragma comment(lib,"oleaut32.lib")
#pragma comment(lib,"uuid.lib")
#pragma comment(lib,"odbc32.lib")
#pragma comment(lib,"odbccp32.lib")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"comdlg32.lib")
#pragma comment(lib,"imagehlp.lib")
#pragma comment(lib,"version.lib")
// *************************************************
// End of Object/Import Libraries To Search
// *************************************************

// *************************************************
//        User's GLOBAL ENUM blocks
// *************************************************

// *************************************************
//            System Defined Constants
// *************************************************

typedef const _TCHAR* ccptr;
#define CCPTR const _TCHAR*
#define cfree free
#define WAITKEY _tsystem(_T("pause"))
#define cSizeOfDefaultString 2048

// *************************************************
//            User Defined Constants
// *************************************************


// *************************************************
//               Standard Prototypes
// *************************************************

void    Pause (void);
// *************************************************
//          User Defined Types And Unions
// *************************************************


interface IComponent  :
IUnknown
{
public:
    void virtual   __stdcall _Print(const _TCHAR*) = 0;
};


class CComponent  : public IComponent
{
public:
    HRESULT virtual   __stdcall QueryInterface(const IID &, void**);
    ULONG virtual   __stdcall AddRef(void);
    ULONG virtual   __stdcall Release(void);
    void virtual   __stdcall _Print(const _TCHAR*);
    CComponent(void);
    ~CComponent(void);

private:
    long     m_cRef;
};


// *************************************************
//            User Global Variables
// *************************************************

static _TCHAR*   *g_argv;
static int     g_argc;


// *************************************************
//               User Prototypes
// *************************************************

IUnknown* CreateInstance (void);
int     _tmain (int, _TCHAR**);

// *************************************************
//            User Global Initialized Arrays
// *************************************************

static const IID     IID_IComponent = {0x853b4626, 0x393a, 0x44df, {0xb1, 0x3e, 0x64, 0xca, 0xbe, 0x53, 0x5d, 0xbf}};


// *************************************************
//                 Runtime Functions
// *************************************************

void Pause(void)
{
    _tprintf(_T("\n%ls\n"), _T("Press any key to continue . . ."));
    _getwch();
}



// ************************************
//       User Subs and Functions
// ************************************

HRESULT __stdcall CComponent::QueryInterface (const IID&  iid, void** ppv)
{
    if(iid == IID_IUnknown )
    {
        _Print(_T("Returning pointer to IUnknown..."));
        *ppv = static_cast< IComponent*>( this);
    }
    else if(iid == IID_IComponent )
    {
        _Print(_T("Returning pointer to IComponent interface..."));
        *ppv = static_cast< IComponent*>( this);
    }
    else
    {
        _Print(_T("Interface is not supported!."));
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();
    return S_OK;
}


ULONG __stdcall CComponent::AddRef ()
{
    _Print(_T("Incrementing the referance count variable..."));
    return InterlockedIncrement( &m_cRef);
}


ULONG __stdcall CComponent::Release ()
{
    _Print(_T("Decrementing the referance count variable..."));
    if(InterlockedDecrement( &m_cRef) == 0 )
    {
        delete this;
        return 0;
    }
    return m_cRef;
}


void CComponent::_Print (const _TCHAR*  msg)
{
    wcout << _T(" Component:\t") << msg << endl;
}


CComponent::CComponent ()
{
    _Print(_T("Constructing the component..."));
    m_cRef = 0;;
}
CComponent::~CComponent ()
{
    _Print(_T("Destructing the component..."));
}
IUnknown* CreateInstance ()
{
    IUnknown*  pIUnknown = (new CComponent);
    return pIUnknown;
}


int _tmain (int argc, _TCHAR** argv)
{
    g_argc = argc;
    g_argv = argv;
    IUnknown*  pIUnknown = CreateInstance();
    IComponent*  pIComponent = NULL;
    pIUnknown->QueryInterface(IID_IComponent, (void**)&pIComponent);
    pIComponent->_Print(_T("COM from scratch"));
    pIComponent->Release();
    Pause();
}













Frederick J. Harris

Funny you should ask James, but its what I'm working on right now.  But with everything I do, it goes slow.  Only one of the three laptops I work on has a 64 bit OS.  At work, we use 32 bit Win 7.  However, my interest in 64 bit COM is twofold.  First, since I work with COM a lot, I ought to explore it in its 64 bit context.  Second, all my work apps we use utilize my 32 but PowerBASIC grid control I've posted here.  Since there have been questions of PowerBASIC, Incs future, I thought I ought to explore C/C++ in its 64 bit context.  The grid control would be the big bugaboo.  Its a central part of all my apps, so I'd have to do that first.

So far I've discovered the 64 bit compiler toolchain seems to be working OK, and that would include MIDL.exe, rc.exe, and cvres.exe.  I'm just doing command line compiling right now.  If anyone's interested, I could post my progress in converting the grid control to 64 bit C++.  Having just started thinking about this, I was agonizing on whether to use C or C++ to create the grid control.  Been going back and forth on that, but I think C++, because I need my String Class - at least the Parse member anyway. 'Course, I could compile as C++ but build the VTables by hand, the way I did in PB.  So, as you can  see, I'm in the early stages of thinking about it yet.

James C. Fuller

Fred,
  Please post your progress.
I have settled on VS12 (aka Visual Studio 2013 Express) for all my current work.
I am using a single batch file to compile 32/64 console, gui, dll, and obj.  It even auto adds non-mangled 32bit stdcall names to dll's.
I just got part-two of the codeproject's COM from scratch working 32/64 in bc9Basic -> c++.
James