Vraag over C++ en COM objecten

Status
Niet open voor verdere reacties.

Jabber

Gebruiker
Lid geworden
8 feb 2007
Berichten
271
Ik wil in mijn eigen Class, zeg Class1, een attribuut toevoegen dat een COM component is. Deze COM component moet dan 'erven' van een Interface.
Dit component is dan verantwoordelijk voor het afhandlen van berichten, over-ge-erfte functie van Interface.

Iemand een idee?
 
Toevallig heb ik net mijn 1e COM programma in C++ gemaakt....

Je moet (ervan uitgaande dat je ms vc++ express gebruikt):

* een odl bestand maken voor je interface en class
* deze compileren naar een typelib (.tlb)
* deze typelib in je resource als typelib includen
* deze typelib en interfaces in de registry zetten onder hun clsid
* IDispatch en Coclasses implementeren
* En een IClassFactory maken

Zie ook:
http://www.codeproject.com/com/com_in_c1.asp
http://www.codeproject.com/com/comintro2.asp

mijn headers:
odl:
PHP:
[
   uuid(840A0BD4-3F05-49d7-95A5-D5CB9BFC37C6), // LIBID_Hello.
   helpstring("CliopWriter 1.0 Type Library."),
   lcid(0),
   version(1)
]
library CliopWriter
{
   importlib("stdole.tlb");

   typedef
   enum{
	   unicaat = 1,
	   duplicaat = 2
   }CDuplicaatCode;

   typedef
   enum{
		produktie = 1,
	    test = 2,
   }CTestCode;

   typedef
   enum{
	   all = 1,
	   break = 0
   }CErrorMode;

   [
	   uuid(8EA58349-FA33-4199-8C2D-31F56971CB6B),
	   helpstring("CTransactie object interface."),
	   oleautomation,
	   dual,
	   odl
   ]
   interface ITransactie : IDispatch
   {
	   [propget]
	   HRESULT __stdcall Bedrag(
		   [out, retval] int* pnBedrag);
	   [propput]
	   HRESULT __stdcall Bedrag(
		   [in] int pnBedrag);
	   [propget]
	   HRESULT __stdcall RekeningNummerBetaler(
		   [out, retval] BSTR* pbstrRekeningNummer);
	   [propput]
	   HRESULT __stdcall RekeningNummerBetaler(
		   [in] BSTR bstrRekeningNummer);
	   [propget]
	   HRESULT __stdcall RekeningNummerBegunstigde(
		   [out, retval] BSTR* pbstrRekeningNummer);
	   [propput]
	   HRESULT __stdcall RekeningNummerBegunstigde(
		   [in] BSTR bstrRekeningNummer);
	   [propget]
	   HRESULT __stdcall NaamBetaler(
		   [out, retval] BSTR* pbstrNaamBetaler);
	   [propput]
	   HRESULT __stdcall NaamBetaler(
		   [in] BSTR bstrNaamBetaler);
	   [propget]
	   HRESULT __stdcall BetalingsKenmerk(
		   [out, retval] BSTR* pbstrKenmerk);
	   [propput]
	   HRESULT __stdcall BetalingsKenmerk(
		   [in] BSTR bstrKenmerk);
	   [propget]
	   HRESULT __stdcall Omschrijving1(
		   [out, retval] BSTR* pbstrOmschrijving);
	   [propput]
	   HRESULT __stdcall Omschrijving1(
		   [in] BSTR bstrOmschrijving);
	   [propget]
	   HRESULT __stdcall Omschrijving2(
		   [out, retval] BSTR* pbstrOmschrijving);
	   [propput]
	   HRESULT __stdcall Omschrijving2(
		   [in] BSTR bstrOmschrijving);
	   [propget]
	   HRESULT __stdcall Omschrijving3(
		   [out, retval] BSTR* pbstrOmschrijving);
	   [propput]
	   HRESULT __stdcall Omschrijving3(
		   [in] BSTR bstrOmschrijving);
	   [propget]
	   HRESULT __stdcall Omschrijving4(
		   [out, retval] BSTR* pbstrOmschrijving);
	   [propput]
	   HRESULT __stdcall Omschrijving4(
		   [in] BSTR bstrOmschrijving);
	   [propget]
	   HRESULT __stdcall WoonplaatsBetaler(
		   [out, retval] BSTR* pbstrWoonplaats);
	   [propput]
	   HRESULT __stdcall WoonplaatsBetaler(
		   [in] BSTR bstrWoonplaats);
   };

   [
	   uuid(DB21C3ED-6019-42af-AB39-60CD0BEECD6D),
	   helpstring("CTransactie object."),
	   noncreatable
   ]
   coclass CTransactie {
	   [default] interface ITransactie;
	   interface IDispatch;
   };

   [
	   uuid(07FC5064-30C7-4bb8-B1A7-3CCEA55608BD),
	   helpstring("CIncassoBatch object interface."),
	   oleautomation,
	   dual,
	   odl
   ]
   interface IIncassoBatch : IDispatch
   {
	   [propget]
	   HRESULT __stdcall RekeningNummerOpdrachtgever(
		   [out, retval] BSTR* pbstrRekeningNummer);
	   [propput]
	   HRESULT __stdcall RekeningNummerOpdrachtgever(
		   [in] BSTR bstrRekeningNummer);
	   [propget]
	   HRESULT __stdcall BatchVolgNummer(
		   [out, retval] int* pnBatchVolgNummer);
	   [propput]
	   HRESULT __stdcall BatchVolgNummer(
		   [in] int nBachtVolgNummer);
	   [propget]
	   HRESULT __stdcall AanleverMuntSoort(
		   [out, retval] BSTR* pbstrMuntSoort);
	   [propput]
	   HRESULT __stdcall AanleverMuntSoort(
		   [in] BSTR bstrMuntSoort);
	   [propget]
	   HRESULT __stdcall VasteOmschrijving1(
		   [out, retval] BSTR* Omschrijving);
	   [propput]
	   HRESULT __stdcall VasteOmschrijving1(
		   [in] BSTR Omschrijving);
	   [propget]
	   HRESULT __stdcall VasteOmschrijving2(
		   [out, retval] BSTR* Omschrijving);
	   [propput]
	   HRESULT __stdcall VasteOmschrijving2(
		   [in] BSTR Omschrijving);
	   [propget]
	   HRESULT __stdcall VasteOmschrijving3(
		   [out, retval] BSTR* Omschrijving);
	   [propput]
	   HRESULT __stdcall VasteOmschrijving3(
		   [in] BSTR Omschrijving);
	   [propget]
	   HRESULT __stdcall VasteOmschrijving4(
		   [out, retval] BSTR* Omschrijving);
	   [propput]
	   HRESULT __stdcall VasteOmschrijving4(
		   [in] BSTR Omschrijving);
	  [propget]
	  HRESULT __stdcall VerwerkingsDatum(
		  [out, retval] DATE* pDate);
	  [propput]
	  HRESULT __stdcall VerwerkingsDatum(
		  [in] DATE dDate);
	  [propget]
	  HRESULT __stdcall NaamOpdrachtgever(
		  [out, retval] BSTR* pbstrNaamOpdrachtgever);
	  [propput]
	  HRESULT __stdcall NaamOpdrachtgever(
		  [in] BSTR bstrNaamOpdrachtgever);
	  [propget]
	  HRESULT __stdcall TestCode(
		  [out, retval] CTestCode* pCode);
	  [propput]
	  HRESULT __stdcall TestCode(
		  [in] CTestCode tcCode);
	  HRESULT __stdcall AddTransactie(
		  [out, retval] ITransactie** ppTransactie);
	  HRESULT __stdcall RemoveTransactie(
		  [in] ITransactie** ppTransactie);
	  HRESULT __stdcall GetTransactieAt(
		  [in] int nIndex,
		  [out, retval] ITransactie** ppTransactie);
	  [propget]
	  HRESULT __stdcall TransactieCount(
		  [out, retval] int* pnCount);
   };

   [
	   uuid(0BED90A9-2EAD-4b36-A138-3932E0066491),
	   helpstring("CIncassoBatch object."),
	   noncreatable
   ]
   coclass CIncassoBatch {
	   [default] interface IIncassoBatch;
	   interface IDispatch;
   };

   [
      uuid(D99B2709-A00D-45fe-A435-8190273CA8C9),   // IID_Ihello.
      helpstring("CCliopWriter application object interface."),
      oleautomation,
      dual,
	  odl
   ]
   interface ICliopWriter : IDispatch
   {
      [helpstring("Adds a CIncassoBatch.")]
      HRESULT __stdcall AddIncassoBatch(
		  [out, retval] IIncassoBatch** ppCIncassoBatch);
	  [helpstring("Removes a CIncassoBatch.")]
	  HRESULT __stdcall RemoveIncassoBatch(
		  [in] IIncassoBatch** ppCIncassoBatch);
	  [helpstring("Returns the CIncassoBatch at index.")]
	  HRESULT __stdcall GetIncassoBatchAt(
		  [in] int nIndex,
		  [out, retval] IIncassoBatch** ppCIncassoBatch);
	  [propget,
	   helpstring("The number of CIncassoBatches.")]
	  HRESULT __stdcall IncassoBatchCount(
		  [out, retval] int* pnCount);
	  [propget]
	  HRESULT __stdcall AanmaakDatum(
		  [out, retval] DATE* CreationDate);
	  [propput]
	  HRESULT __stdcall AanmaakDatum(
		  [in] DATE CreationDate);
	  [propget]
	  HRESULT __stdcall BestandsNaam(
		  [out, retval] BSTR* BestandsNaam);
	  [propget]
	  HRESULT __stdcall InzenderIdentificatie(
		  [out, retval] BSTR* InzenderIdentificatie);
	  [propput]
	  HRESULT __stdcall InzenderIdentificatie(
		  [in] BSTR InzenderIdentificatie);
	  [propget]
	  HRESULT __stdcall DuplicaatCode(
		  [out, retval] CDuplicaatCode* DuplicaatCode);
	  [propput]
	  HRESULT __stdcall DuplicaatCode(
		  [in] CDuplicaatCode DuplicaatCode);
	  HRESULT __stdcall Check(
		  [in] CErrorMode Mode,
		  [out, retval] VARIANT_BOOL* Ok);
	  [propget]
	  HRESULT __stdcall ErrorMessage(
		  [out, retval] BSTR* pbstrMessage);
	  [propget]
	  HRESULT __stdcall ErrorObject(
		  [out, retval] IDispatch** ppObject);
	  [propget]
	  HRESULT __stdcall SaveFileName(
		  [out, retval] BSTR* pbstrFileName);
	  [propput]
	  HRESULT __stdcall SaveFileName(
		  [in] BSTR bstrFileName);
	  HRESULT __stdcall Save(
		  [out, retval] VARIANT_BOOL* pbSuccess);
	  HRESULT __stdcall SaveAs(
		  [out, retval] VARIANT_BOOL* pbSuccess);
   };

   [
		uuid(7B1D687D-0D03-41f4-9D3C-5DF61482BB99),
		helpstring("CCliopWriter application object."),
		appobject
   ]
   coclass CCliopWriter {
	    [default] interface ICliopWriter;
		interface IDispatch;
   };
}

cliopwriter.h
PHP:
#ifndef _CLIOPWRITER_H
#define _CLIOPWITER_H

#include <windows.h>
#include <vector>
#include "dispatchable.cpp"
#include "incassobatch.h"
#include "cwbstr.h"

typedef enum {
	unicaat = 1,
	duplicaat = 2
}CDuplicaatCode;

/*
	Interface definition
*/
struct ICliopWriter : public IDispatch
{
	STDMETHOD_(ULONG, AddRef)() PURE;
	STDMETHOD_(ULONG, Release)() PURE;
	STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) PURE;
	STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) PURE;
	STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) PURE;
	STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) PURE;
	STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr) PURE;
	STDMETHOD(AddIncassoBatch)(CIncassoBatch** ppIncassoBatch) PURE;
	STDMETHOD(RemoveIncassoBatch)(CIncassoBatch** ppIncassoBatch) PURE;
	STDMETHOD(GetIncassoBatchAt)(int nIndex, CIncassoBatch** ppIncassoBatch) PURE;
	STDMETHOD(getIncassoBatchCount)(int* pnCount) PURE;
	STDMETHOD(getCreationDate)(DATE* pDate) PURE;
	STDMETHOD(setCreationDate)(DATE Date) PURE;
	STDMETHOD(getFileName)(BSTR* pbstrFileName) PURE;
	STDMETHOD(getInzenderID)(BSTR* pbstrInzenderID) PURE;
	STDMETHOD(setInzenderID)(BSTR pbstrInzenderID) PURE;
	STDMETHOD(getDuplicaatCode)(CDuplicaatCode* pDuplicaatCode) PURE;
	STDMETHOD(setDuplicaatCode)(CDuplicaatCode DuplicaatCode) PURE;
	STDMETHOD(Check)(BOOL bAll, VARIANT_BOOL* bOk) PURE;
	STDMETHOD(getErrorMessage)(BSTR* pbstrMessage) PURE;
	STDMETHOD(getErrorObject)(IDispatch** ppObject) PURE;
	STDMETHOD(getSaveFileName)(BSTR* pbstrFileName) PURE;
	STDMETHOD(setSaveFileName)(BSTR bstrFileName) PURE;
	STDMETHOD(Save)(VARIANT_BOOL* pbSuccess) PURE;
	STDMETHOD(SaveAs)(VARIANT_BOOL* pbSuccess) PURE;
};

struct __declspec(uuid("{D99B2709-A00D-45fe-A435-8190273CA8C9}")) ICliopWriter;

class CCliopWriter : public CWDispatchable<ICliopWriter>
{
public:
	CCliopWriter();
	virtual ~CCliopWriter();

	static HRESULT Create(REFCLSID rclid, void** ppvObject);

	STDMETHOD(AddIncassoBatch)(CIncassoBatch** ppIncassoBatch);
	STDMETHOD(RemoveIncassoBatch)(CIncassoBatch** ppIncassoBatch);
	STDMETHOD(GetIncassoBatchAt)(int nIndex, CIncassoBatch** ppIncassoBatch);
	STDMETHOD(getIncassoBatchCount)(int* pnCount);
	STDMETHOD(getCreationDate)(DATE* pDate);
	STDMETHOD(setCreationDate)(DATE Date);
	STDMETHOD(getFileName)(BSTR* pbstrFileName);
	STDMETHOD(getInzenderID)(BSTR* pbstrInzenderID);
	STDMETHOD(setInzenderID)(BSTR pbstrInzenderID);
	STDMETHOD(getDuplicaatCode)(CDuplicaatCode* pDuplicaatCode);
	STDMETHOD(setDuplicaatCode)(CDuplicaatCode DuplicaatCode);
	STDMETHOD(Check)(BOOL bAll, VARIANT_BOOL* bOk);
	STDMETHOD(getErrorMessage)(BSTR* pbstrMessage);
	STDMETHOD(getErrorObject)(IDispatch** ppObject);
	STDMETHOD(getSaveFileName)(BSTR* pbstrFileName);
	STDMETHOD(setSaveFileName)(BSTR bstrFileName);
	STDMETHOD(Save)(VARIANT_BOOL* pbSuccess);
	STDMETHOD(SaveAs)(VARIANT_BOOL* pbSuccess);
private:
	std::vector<CIncassoBatch*> m_IncassoVector;
	DATE m_CreationDate;
	static const BSTR m_lpbszFileName;
	CWBstr m_InzenderID;
	CDuplicaatCode m_DuplicaatCode;
	CWBstr m_ErrorMessage;
	IDispatch* m_pErrorObject;
	CWBstr m_SaveFileName;
};

class __declspec(uuid("{7B1D687D-0D03-41f4-9D3C-5DF61482BB99}")) CCliopWriter;

typedef HRESULT (*FPCOMPCREATOR)(REFCLSID, void**);

struct ClassFactoryInfo
{
	const CLSID CLSID;
	FPCOMPCREATOR pFunc;
};

class CCliopWriterClassFactory : public IClassFactory
{
public:
	CCliopWriterClassFactory(FPCOMPCREATOR fpCompCreator);
	virtual ~CCliopWriterClassFactory();

	ULONG STDMETHODCALLTYPE AddRef();
	ULONG STDMETHODCALLTYPE Release();
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);

	HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown* pUnkOuter, REFIID riid, void **ppvObject);
	HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);

private:
	UINT	m_uRefCount;
	FPCOMPCREATOR m_fpCompCreator;
};

#endif // _CLIOPWITER

resource:
PHP:
1 typelib Debug/cliopwriter.tlb
 
Laatst bewerkt:
Dat is niet helemaal wat ik bedoel.
Wat jij opnoemt heb ik al. Dat werkt correct. Als nu 1 van deze
functies laat overerven door een andere klasse, hoe kan ik deze andere
klasse insantieren?
 
Ik weet niet helemaal zeker of ik goed begrijp wat je bedoelt, maar bedoel je dat je een basisklasse voor alle IDispatch klassen wilt gebruiken?
Dit kan nl niet omdat virtual members van de basisklasse die niet in de IDispatch struct gedefineeerd zijn na de virtual member van IDispatch in de virtual call table komen en dan pas de nieuw declareerde virtual members. Ik heb dit opgelost door een template klasse te gebruiken.

ps. Ik zit nu zelf ongelovelijk te klooien met BSTR's. De set methods van een property nemen een kloon van de waarde en de get methods geven ook een kloon van de waarde terug. Als ik mijn interface in de vb debugger van access draai crasht access zonder melding als ik door mijn vb test code step. Als ik niet step draait het als een zonnetje....jij toevallig enig idee?
 
VC++ 6.0
Mappoint 2006

Hallo beste programmeurs,

Ik heb weinig verstand van COM en hoop dat jullie mij kunnen helpen.
Ik gebruik Mappoint COM en wil de ID van bepaalde interfaces achterhalen. Want ik krijg bij selectie events verschillende interfaces, maar ik weet niet met wat voor interfaces ik te maken heb. Het is zeg maar als volgt:

__________________________
l l
l Mappoint COM l
l_________________________ l UUID: ????
l
l- Map ID: ???????
l- Application ID: ??????
l- Location ID: ??????
l- Pushpin ID: ??????
l- Shape ID: ??????
l- .......
l- .......
l- .......
:
:

Dus ik wil weten wat de ID's zijn, maar weet niet zo gauw hoe.
Verder heb ik de volgende memberfuncties.
. AddRef()
. GetIDsOfNames(...)
. GetTypeInfoCount(...)
. Invoke(...)
. QueryInterfaces(...)
. Release()

Mappoint object heb ik geïmporteerd mbv de Wizard en kreeg daarna gelijk een Map control in mijn controlbar toegevoegd.
 
Laatst bewerkt:
Gelieve een eigen topic te starten, we gaan op dit moment off topic.
Maar een antwoord op je vraag heb ik helaas niet. Ik heb er nog nooit gebruik van gemaakt.

@dropl: Geen idee, zie andere topic.
 
Laatst bewerkt:
Bedankt voor je reaktie Jabber,

Met alle respekt Jabber, maar ik vraag iets over COM die ik gebruik in VC++. De techniek is hetzelfde, alleen heb ik een probleem bij de COM techniek.
 
Je heb gelijk, ik dacht dat ik met een duidelijker/preciezere topic titel was gestart. Maar dat was helaas niet het geval, mijn excuses voor mijn reaktie.

Maar wanneer je je eigen topic (vraag) start, dan kunnen er niet meerdere vragen door elkaar lopen. Is denk toch iets makkelijker. Neemt niet weg dat ik een wat duidelijker titel had moeten kiezen.

Met vriendelijke groet,
Jabber.

PS. Is het nog gelukt?
 
Dank je wel voor je reaktie Jabber,

Het is nog niet echt gelukt nee. Ik ben best gefrustreerd om die COM gedoe. Het is namelijk moeilijk een oplossing op het net te vinden. Het is eigenlijk heel simpel, is COM-interface van xxxx ID? Ja, dan doe dit, Nee, dan doe dat. Dus alleen het bepalen van de juiste ID van een interface heeft mij al een week gekost. En nergens een normaal uitleg. Bij COM moet je of alles weten of niks weten, ergens tussen in is gewoon hel. Want dan weet je het toevallig wel, of lukt het dit keer wel en dan ander keer is het Chinees.
 
hehe, ik ken het gevoel.
Ik kan het alleen als er ik via de wizard iets ga maken. Als het iets exotisch is, dan moet ik al afhaken. Het is niet de makkelijkste materie die ik ben tegengekomen.

Maar als het eenmaal draait (opletten op memory leakage) dan is er niets aan de hand en draait het als een zonnetje.
 
Ik mag er vanwege geheimhoudingsplicht op het werk niet teveel over uitweiden.
Maar het volgende kan ik vertellen:

[Huidig]
GUI : COM component.
Bussiness laag: Meerdere COM componenten. (database, xml, en protocol specifieke componenten)
Machine laag: COM componenten die de besturing van de machine aansturen.

[Eerder]
- C++ op Embedded systemen.
- C# ASP.NET.
 
Hoi Jabber,

Bedankt voor je reply, sorry dat ik je niet eerder kon beantwoorden, was het helemaal vergeten door m'n werk.

Ik kan me best voorstellen dat je niet te veel mag zeggen over je werk dus heb ik vrede mee, eerlijk gezegd is dat bij mij ook zo. Ik werk namelijk voor de Veiligheidsdienst en orde handhavers, meer kan ik ook niet vertellen.

Je hebt eerder C++ geprogrammeerd voor embedded systems, dat lijkt me erg interessant. Hoe was jouw ervaring en wat deed je daar precies toen. Ik vind zelf namelijk erg leuk om embedded systems te programmeren, zoals microcontrollers, embedded pc's en pda's. Ik heb zelf een Renesas uC 8-bits, zo een kleintje en een ARM7 uC. Ik wil me vooral in de ARM processors verdiepen.
 
Ook daar kan ik me weinig over uitdiepen,
maar ik heb met de ARM, XA, MC 68000 en PIC Controller gewerkt.
Vooral in de ARM omgeving met de Tasking EDE.

Het is me wel erg goed bevallen en erg leuk om te doen. Echter wil ik nu, persoonlijke ontwikkeling, me meer met .NET bezig houden. De COM klus is een klus tussendoor.
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan