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
I haven't tried anything 64-bit related yet.
Far from being phased, winRT is all COM.
QuoteHave you investigated 64bit COM ?
No, i must first complete the translation of my graphic LIBs, before i can play with it.
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.
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.
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();
}
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.
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