COM Tutorial #1: COM Object Memory

Started by Frederick J. Harris, January 20, 2009, 08:38:02 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Frederick J. Harris

Just this (which you must have seen)....

http://www.jose.it-berater.org/smfforum/index.php?topic=4018.0

I believe it was last fall I spent like about a whole week trying desperately to use GNU mingw and Code::Blocks to create COM dlls but completely failed.  I asked about it at Daniweb (big C++ site), but no one could help.  Where it comes apart is with *.def files.  They appear to be the only way to create COM dlls with C/C++, and mingw can't get them right.

I still use my VC 6 for most C/C++ fooling around with COM I do.  I have VS 2008 pro too but far as I'm concerned its a pita.

James C. Fuller

How about a PowerBASIC DUAL  com server and c++ vtable access code? Or how to approach it?

James

James C. Fuller

Fred,
  I have working code using PowerBASIC dll server inherited from IUNKNOWN but not with DUAL.
My c++ is so poor it is probably on that end but I just don't know. It is probably the virtual class layout??
Note the c++ code was created with Bcx. It compiles with both MinGw and vs2010.

James

PowerBASIC IUNKNOWN server

#COMPILE DLL "PBTEST10_UNK.DLL"
#DIM ALL
#COM TLIB ON
#COM NAME "PBTEST10_UNK"
#COM GUID GUID$ ("{B3723C2A-7DCF-437A-AF59-42F19122B39B}")
#RESOURCE TYPELIB,1,"PBTEST10_UNK.TLB"

#INCLUDE ONCE "WIN32API.INC"
MACRO PropGet(PropName,PropType)=PROPERTY GET PropName() AS PropType:PROPERTY=PropName:END PROPERTY
MACRO PropSet(PropName,PropType)=PROPERTY SET PropName(BYVAL param AS PropType):PropName=param:END PROPERTY


$cPbTest10Guid = GUID$("{0D7051A6-456A-4631-9878-1B7FA5433539}")
$iPbTest10Guid = GUID$("{EAA6ED6B-B73D-44B6-832E-1B4BE67032D3}")

CLASS cPbTest10 $cPbTest10Guid AS COM
    INSTANCE p1 AS LONG


    CLASS METHOD CREATE
        p1 = 77
        STDOUT "Hello From the pbtest10_unk com server create method"
    END METHOD

    INTERFACE iPbTest10 $iPbTest10Guid : INHERIT IUNKNOWN
        PropGet(p1,LONG)
        PropSet(p1,LONG)
    END INTERFACE
END CLASS


'==============================================================================
'MCM code
'------------------------------------------------------------------------------
FUNCTION STDOUT (Z AS STRING) AS LONG
' returns TRUE (non-zero) on success

   LOCAL hStdOut AS LONG, nCharsWritten AS LONG
   LOCAL w AS STRING


   hStdOut      = GetStdHandle (%STD_OUTPUT_HANDLE)
   IF hSTdOut   = -1&  OR hStdOut = 0&  THEN     ' invalid handle value, coded in line to avoid
                                                 ' casting differences in Win32API.INC
                                                 ' %NULL test added for Win/XP
     AllocConsole
     hStdOut  = GetStdHandle (%STD_OUTPUT_HANDLE)
   END IF
   w = Z & $CRLF
   FUNCTION = WriteFile(hStdOut, BYVAL STRPTR(W), LEN(W),  nCharsWritten, BYVAL %NULL)


END FUNCTION
'==============================================================================


The c++ code that compiles and works with the above server


// *********************************************************************
// Created with BCX32 - BASIC To C/C++ Translator (V) 8.7.0.0 (2011/05/11)
//                 BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
//              Translated for compiling with a C++ Compiler
// *********************************************************************
// Additional lines may be needed
#if defined( __cplusplus )
  using namespace std;
  #include <iostream>
  #include <fstream>
  #include <sstream>
  #include <iomanip>
  typedef std::string stdstr;
#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 <richedit.h>   // Win32 Header File
#include <wchar.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 <process.h>    // dos
#include <conio.h>      // dos
#include <direct.h>     // dos
#include <io.h>         // dos
#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 <stddef.h>     // dos/linux
#include <stdlib.h>     // dos/linux
#include <setjmp.h>     // dos/linux
#include <time.h>       // dos/linux
#include <stdarg.h>     // dos/linux


// ***************************************************
// 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

// Open Watcom defs
#if defined( __WATCOM_CPLUSPLUS__ ) || defined( __TINYC__ )
  #define atanl atan
  #define sinl  sin
  #define cosl  cos
  #define tanl  tan
  #define asinl asin
  #define acosl acos
  #define log10l log10
  #define logl   log
  #define _fcloseall fcloseall
#endif

// Borland C++ 5.5.1 defs - bcc32.exe
#if defined( __BCPLUSPLUS__ )
  // ===== Borland Libraries ==========
  #include <dos.h>
  #pragma comment(lib,"import32.lib")
  #pragma comment(lib,"cw32.lib")
  // ==================================
#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

// *************************************************
#ifndef __cplusplus
  #error A C++ compiler is required
#endif

#if !defined( __LCC__ )
// *************************************************
// 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")
#else
#pragma lib <winspool.lib>
#pragma lib <shell32.lib>
#pragma lib <ole32.lib>
#pragma lib <oleaut32.lib>
#pragma lib <uuid.lib>
#pragma lib <odbc32.lib>
#pragma lib <odbccp32.lib>
#pragma lib <winmm.lib>
#pragma lib <imagehlp.lib>
#pragma lib <version.lib>
// *************************************************
// End of Object/Import Libraries To Search
// *************************************************
#endif

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

#define cSizeOfDefaultString 2048
#define GetClassObj(dll) (HRESULT(__stdcall*)(REFCLSID,REFIID,void**))GetProcAddress(hDll,"DllGetClassObject")

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

void    Pause (void);

// *************************************************
//          User Defined Types And Unions
// *************************************************

class IPbTest10: public IUnknown
  {
  public:
virtual long __stdcall p1_get();
virtual void __stdcall p1_set(long);
  };

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



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

int     main (int,PCHAR*);

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

static const CLSID   CLSID_cPbTest10Guid={0x0D7051A6,0x456A,0x4631,{0x98,0x78,0x1B,0x7F,0xA5,0x43,0x35,0x39}};
static const IID     IID_iPbTest10Guid={0xEAA6ED6B,0xB73D,0x44B6,{0x83,0x2E,0x1B,0x4B,0xE6,0x70,0x32,0xD3}};


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

void Pause(void)
{
  printf("\n%s\n","Press any key to continue . . .");
  _getch();
}


HRESULT( __stdcall*ptrDllGetClassObject)(const CLSID&,const IID&,void**);

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


int main (int argc,PCHAR* argv)
{
  IPbTest10*  pPbt=NULL;
  HRESULT  hr;
  IClassFactory*  pCF=NULL;
  HMODULE  hDll=NULL;
  BSTR     str1;
  long     l;
  static char    stemp[cSizeOfDefaultString];
  hDll=LoadLibrary("D:\\ComTutorial1A\\Server\\PbSource\\PBTEST10_UNK.DLL");
  if(!hDll )
    {
      MessageBox (GetActiveWindow(),"Bad Load","",0);
      return 0;
    }
  ptrDllGetClassObject=GetClassObj(hDll);
  hr=ptrDllGetClassObject(CLSID_cPbTest10Guid,IID_IClassFactory,(void**)&pCF);
  if((SUCCEEDED(hr)))
    {
      pCF->CreateInstance(NULL,IID_iPbTest10Guid,(void**)&pPbt);
      pCF->Release();
      l=pPbt->p1_get();
      cout<<" l = "<<l<<endl;
      pPbt->p1_set(128);
      l=pPbt->p1_get();
      cout<<" l = "<<l<<endl;
      hr=pPbt->Release();
    }
  if(hDll )
    {
      FreeLibrary(hDll);
    }
  Pause();
  return 0;
}



The PowerBASIC DUAL code



#COMPILE DLL "PBTEST10_DUAL.DLL"
#DIM ALL
#COM TLIB ON
#COM NAME "PBTEST10_DUAL"
#COM GUID GUID$("{F86AA908-0A93-4F64-8E36-549A4850AA64}")
#RESOURCE TYPELIB,1,"PBTEST10_DUAL.TLB"

#INCLUDE ONCE "WIN32API.INC"
MACRO PropGet(PropName,PropType)=PROPERTY GET PropName() AS PropType:PROPERTY=PropName:END PROPERTY
MACRO PropSet(PropName,PropType)=PROPERTY SET PropName(BYVAL param AS PropType):PropName=param:END PROPERTY


$cPbTest10Guid = GUID$("{F455D1C8-37A2-40DD-901D-59D8EE7C33D2}")
$iPbTest10Guid = GUID$("{DDD0F77A-A178-4B88-A115-B80DD9FD7AED}")

CLASS cPbTest10 $cPbTest10Guid AS COM
    INSTANCE p1 AS LONG


    CLASS METHOD CREATE
        p1 = 77
        STDOUT "Hello From the pbtest10_dual com server create method"
    END METHOD

    INTERFACE iPbTest10 $iPbTest10Guid : INHERIT DUAL
        'PropGet(p1,LONG)
        'PropSet(p1,LONG)
        METHOD p1_get() AS LONG
            METHOD = p1
        END METHOD

        METHOD p1_set(p AS LONG)
            p1 = p
        END METHOD

    END INTERFACE
END CLASS


'==============================================================================
'MCM code
'------------------------------------------------------------------------------
FUNCTION STDOUT (Z AS STRING) AS LONG
' returns TRUE (non-zero) on success

   LOCAL hStdOut AS LONG, nCharsWritten AS LONG
   LOCAL w AS STRING


   hStdOut      = GetStdHandle (%STD_OUTPUT_HANDLE)
   IF hSTdOut   = -1&  OR hStdOut = 0&  THEN     ' invalid handle value, coded in line to avoid
                                                 ' casting differences in Win32API.INC
                                                 ' %NULL test added for Win/XP
     AllocConsole
     hStdOut  = GetStdHandle (%STD_OUTPUT_HANDLE)
   END IF
   w = Z & $CRLF
   FUNCTION = WriteFile(hStdOut, BYVAL STRPTR(W), LEN(W),  nCharsWritten, BYVAL %NULL)


END FUNCTION
'==============================================================================


and the c++ that fails.


// *********************************************************************
// Created with BCX32 - BASIC To C/C++ Translator (V) 8.7.0.0 (2011/05/11)
//                 BCX (c) 1999 - 2009 by Kevin Diggins
// *********************************************************************
//              Translated for compiling with a C++ Compiler
// *********************************************************************
// Additional lines may be needed
#if defined( __cplusplus )
  using namespace std;
  #include <iostream>
  #include <fstream>
  #include <sstream>
  #include <iomanip>
  typedef std::string stdstr;
#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 <richedit.h>   // Win32 Header File
#include <wchar.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 <process.h>    // dos
#include <conio.h>      // dos
#include <direct.h>     // dos
#include <io.h>         // dos
#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 <stddef.h>     // dos/linux
#include <stdlib.h>     // dos/linux
#include <setjmp.h>     // dos/linux
#include <time.h>       // dos/linux
#include <stdarg.h>     // dos/linux


// ***************************************************
// 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

// Open Watcom defs
#if defined( __WATCOM_CPLUSPLUS__ ) || defined( __TINYC__ )
  #define atanl atan
  #define sinl  sin
  #define cosl  cos
  #define tanl  tan
  #define asinl asin
  #define acosl acos
  #define log10l log10
  #define logl   log
  #define _fcloseall fcloseall
#endif

// Borland C++ 5.5.1 defs - bcc32.exe
#if defined( __BCPLUSPLUS__ )
  // ===== Borland Libraries ==========
  #include <dos.h>
  #pragma comment(lib,"import32.lib")
  #pragma comment(lib,"cw32.lib")
  // ==================================
#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

// *************************************************
#ifndef __cplusplus
  #error A C++ compiler is required
#endif

#if !defined( __LCC__ )
// *************************************************
// 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")
#else
#pragma lib <winspool.lib>
#pragma lib <shell32.lib>
#pragma lib <ole32.lib>
#pragma lib <oleaut32.lib>
#pragma lib <uuid.lib>
#pragma lib <odbc32.lib>
#pragma lib <odbccp32.lib>
#pragma lib <winmm.lib>
#pragma lib <imagehlp.lib>
#pragma lib <version.lib>
// *************************************************
// End of Object/Import Libraries To Search
// *************************************************
#endif

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

#define cSizeOfDefaultString 2048
#define GetClassObj(dll) (HRESULT(__stdcall*)(REFCLSID,REFIID,void**))GetProcAddress(hDll,"DllGetClassObject")

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

char*   BCX_TmpStr(size_t,size_t= 128,int= 1);
char*   curdir (void);
void    Pause (void);

// *************************************************
//          User Defined Types And Unions
// *************************************************

class IPbTest10: public IDispatch
  {
  public:
virtual long __stdcall p1_get();
virtual void __stdcall p1_set(long);
  };

// *************************************************
//                System Variables
// *************************************************


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



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

int     main (int,PCHAR*);

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

static const CLSID   CLSID_cPbTest10Guid={0xF455D1C8,0x37A2,0x40DD,{0x90,0x1D,0x59,0xD8,0xEE,0x7C,0x33,0xD2}};
static const IID     IID_iPbTest10Guid={0xDDD0F77A,0xA178,0x4B88,{0xA1,0x15,0xB8,0x0D,0xD9,0xFD,0x7A,0xED}};


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

#ifndef BCXTmpStrSize
#define BCXTmpStrSize  2048
#endif
char *BCX_TmpStr (size_t Bites,size_t  iPad,int iAlloc)
{
  static int   StrCnt;
  static char *StrFunc[BCXTmpStrSize];
  StrCnt=(StrCnt + 1) & (BCXTmpStrSize-1);
  if(StrFunc[StrCnt]) {free (StrFunc[StrCnt]); StrFunc[StrCnt] = NULL;}
#if defined BCX_MAX_VAR_SIZE
  if(Bites*sizeof(char)>BCX_MAX_VAR_SIZE)
  {
  printf("Buffer Overflow caught in BCX_TmpStr - requested space of %d EXCEEDS %d\n",(int)(Bites*sizeof(char)),BCX_MAX_VAR_SIZE);
  abort();
  }
#endif
  if(iAlloc) StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
  return StrFunc[StrCnt];
}


char *curdir (void)
{
  register char *strtmp = BCX_TmpStr(2048);
  GetCurrentDirectory (1024,strtmp);
  return strtmp;
}


void Pause(void)
{
  printf("\n%s\n","Press any key to continue . . .");
  _getch();
}


HRESULT( __stdcall*ptrDllGetClassObject)(const CLSID&,const IID&,void**);

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


int main (int argc,PCHAR* argv)
{
  IPbTest10*  pPbt=NULL;
  HRESULT  hr;
  IClassFactory*  pCF=NULL;
  HMODULE  hDll=NULL;
  BSTR     str1;
  long     l;
  static char    stemp[cSizeOfDefaultString];
  strcpy(stemp,curdir());
  hDll=LoadLibrary("D:\\ComTutorial1A\\Server\\PbSource\\PBTEST10_DUAL.DLL");
  if(!hDll )
    {
      MessageBox (GetActiveWindow(),"Bad Load","",0);
      return 0;
    }
  ptrDllGetClassObject=GetClassObj(hDll);
  hr=ptrDllGetClassObject(CLSID_cPbTest10Guid,IID_IClassFactory,(void**)&pCF);
  if((SUCCEEDED(hr)))
    {
      pCF->CreateInstance(NULL,IID_iPbTest10Guid,(void**)&pPbt);
      pCF->Release();
      l=pPbt->p1_get();
      cout<<" l = "<<l<<endl;
      pPbt->p1_set(128);
      l=pPbt->p1_get();
      cout<<" l = "<<l<<endl;
    }
  if(hDll )
    {
      FreeLibrary(hDll);
    }
  Pause();
  return 0;
}




I examined the dual tlb with oleview and there are both IDispatch with the HRESULT returns and the IUnknown but how to get the IUnknown???




Frederick J. Harris

Gimme a little time to familiarize myself with it.  Actually, that Dual interface example I gave a link to above (COM Tutorial #4) seems to be what you are interested in.  I didn't put too much in the way of comments in it like I did the others I see.  From a C++ perspective using IDispatch in C++ clients isn't something done unless one is a glutton for punishennt.  You have to declare arrays or Variants, load the variants with various required info, etc., etc.  Painful.  Once you go through with jumping all the hurdles though, it works fine.

I see you are just trying to use direct access in your C++ code that is failing though.  Like I said, I'll look at it.

By the way, I do have a debug version of that COM #4 IDispatch code with piles of debug printf statements in it if you want it.  Actually, that's how I code/debug.  I either output mountains of debug statements to the console or a log file.

James C. Fuller

Fred,
I have no desire to connect using IDispatch. My understanding (?) is a dual interface has both IDispatch and vtable. I want to connect using c++ and vtable of an unregistered and/or a registered interface. My code shows loading an unregistered but maybe this is not possible with a dual interface??
Thanks for taking a look.

James

James C. Fuller

Fred,
  I just took a look at the other code.
How does one return a value as in my IUnknown example ?

James

James C. Fuller

Fred,
  From an Inside COM makefile I found the parameters for midl:

#################################################
#
# Proxy source files
#
Iface.h Server.tlb Proxy.c Guids.c DllData.c : Server.idl
   midl /h Iface.h /iid Guids.c /proxy Proxy.c Server.idl

#################################################

James

Frederick J. Harris

Hi James!

    Its kind of like I thought.  Funny stuff goes on.  I compiled the PBTEST10_DUAL.dll and registered it with RegSvr32 (didn't feel like playing with function pointers today).  Here is a PB 6 program that accesses it...


'Console Compiler 6
#Compile Exe
#Dim All

$CLSID_CPBTEST10 = Guid$("{F455D1C8-37A2-40DD-901D-59D8EE7C33D2}")
$IID_IPBTEST10   = Guid$("{DDD0F77A-A178-4B88-A115-B80DD9FD7AED}")

' Interface Name  : IPBTEST10
' Description     : IPBTEST10 is a dual interface with VTable/Dispatch access.
' Class Name      : CPBTEST10
' ClassID         : $CLSID_CPBTEST10
Interface IPBTEST10 $IID_IPBTEST10 : Inherit IDispatch
  Method P1_GET <257> () As Long
  Method P1_SET <258> (ByRef InOut P As Long)
End Interface

Function PBMain() As Long
  Local pIPbTest10 As IPBTEST10

  pIPbTest10=NewCom(ProgId$($CLSID_CPBTEST10))
  If IsObject(pIPbTest10) Then
     Print "pWhatever Is An Object!"
     pIPbTest10.p1_Set(25)
     Print "pIPbTest10.p1_Get() = " pIPbTest10.p1_Get()
     Set pIPbTest10=Nothing
  Else
     Print "pWhatever Ain't Crap!"
  End If
  Con.WaitKey$

  PBMain=0
End Function

'Hello From the pbtest10_dual com server create method
'pWhatever Is An Object!
'pIPbTest10.p1_Get() =  25


...and here is a C++ program that does the same (direct access)...


#include <windows.h>
#include <stdio.h>
const CLSID CLSID_CPBTEST10 = {0xF455D1C8,0x37A2,0x40DD,{0x90,0x1D,0x59,0xD8,0xEE,0x7C,0x33,0xD2}};
const IID   IID_IPBTEST10   = {0xDDD0F77A,0xA178,0x4B88,{0xA1,0x15,0xB8,0x0D,0xD9,0xFD,0x7A,0xED}};

interface IPBTest : IDispatch
{
virtual HRESULT __stdcall p1_Get(int* pInt);
virtual HRESULT __stdcall p1_Set(int* pNum);
};

int main(void)
{
IPBTest* pTest=NULL;
int iNumber=0;
HRESULT hr;

OleInitialize(NULL);
hr=CoCreateInstance(CLSID_CPBTEST10,NULL,CLSCTX_INPROC_SERVER,IID_IPBTEST10,(void**)&pTest);
if(SUCCEEDED(hr))
{
    printf("CoCreateInstance() Succeeded!\n");
    hr=pTest->p1_Get(&iNumber);
    if(SUCCEEDED(hr))
       printf("iNumber = %d\n",iNumber);
    pTest->Release();
}
OleUninitialize();
getchar();

return 0;
}

/*
Hello From the pbtest10_dual com server create method
CoCreateInstance() Succeeded!
iNumber = 77
*/


Note the funny business with the hidden HRESULT between the PB and C code.

Frederick J. Harris

If you redo the prototype for the 'get' to pass in a pointer for a [retval] I'm thinking it'll work.

Frederick J. Harris

Since there aren't too many parameters IDispatch wouldn't be bad.

Frederick J. Harris

Of course, OleView shows the 'hidden' parameter.

James C. Fuller

Fred,
 Thank you very much.
Now how about IDictionary from scrrun.dll from vtable c++ :)

James