Using the COM interface with VS2017 and plain C++

Post a reply


In an effort to prevent automatic submissions, we require that you complete the following challenge.
Smilies
:D :) :( :o :-? 8) :lol: :x :P :oops: :cry: :evil: :roll: :wink:

BBCode is ON
[img] is ON
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Using the COM interface with VS2017 and plain C++

Re: Using the COM interface with VS2017 and plain C++

by mcow » Fri Jun 21, 2019 5:03 pm

Dave Plummer, I have been doing more intensive work with this lately, and created some C++ code for dealing with the COM objects. When you get an IDispatch object, you need to look up the "DISPID" for the method(s) you want to call and then invoke them. This works roughly like (no guarantees this will compile as written):

Code: Select all

	// your code from the earlier post
	ISDBDatabase *pSDBDatabase;
	pSDB->get_Database(&pSDBDatabase);
	BSTR qs = SysAllocString(L"Author='Berio, Adolfo'");
	IDispatch *pIDisp;
	pSDBDatabase->QuerySongs(qs, &pIDisp);

	// what do do next
	HRESULT hr;
	// Repeat the following for each method or property, save the IDs
	wchar_t cname[]=L"EOF";
	DISPID id;
	hr = pIDisp->GetIDsOfNames(IID_NULL, &cname, 1, LOCALE_USER_DEFAULT, &id);
	
	// then, to retrieve this property value:
	DISPPARAMS dp = { NULL, NULL, 0, 0 };
	VARIANT result;
	hr = pIDisp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
			&dp, &result, NULL, NULL);
	bool eof = result.boolVal;
Method calls use DISPATCH_METHOD instead of _PROPERTYGET, and passing parameters is done via the DISPPARAMS object. Setting properties can also be done but with additional DISPPARAMS setup.

I don't understand why that "working fragment" you posted before works for you, since the CoCreateInstance() method also returns an IDispatch. Anyway, if you're still interested in getting this to work, DM me and I'll share some generic C++ code I've written to create classes that wrap the IDispatch with maybe a little less pain.

Re: Using the COM interface with VS2017 and plain C++

by mcow » Sun Mar 17, 2019 10:08 pm

Dave Plummer, I just wandered back into this forum after a few years away. I saw your question about using IDispatch.

In this Wiki page I wrote some time ago, I have an example of using PyIDispatch.Invoke(), in the OnTrackSkipped() handler.
Honestly, it's been a long time and I don't remember how to interpret what you see there, but maybe that will give you a leg up on using IDispatch.

Re: Using the COM interface with VS2017 and plain C++

by Peke » Thu Jun 21, 2018 9:37 am

Hi,
In any other languages I used I simply ignored definitions like "IDispatch *pIDisp;" and assumed directly "ISDBSongIterator* pSDBIterator" which would result in "something like pSDBDatabase->QuerySongs(qs, &pSDBIterator);"

Re: Using the COM interface with VS2017 and plain C++

by dplummer » Thu Jun 21, 2018 6:43 am

Thanks for the reply Pavle,

This is not quite right and I am still struggling.

My code is:

Code: Select all

		ISDBDatabase *pSDBDatabase;
		pSDB->get_Database(&pSDBDatabase);
		BSTR qs = SysAllocString(L"Author='Berio, Adolfo'");
		IDispatch *pIDisp;
		pSDBDatabase->QuerySongs(qs, &pIDisp);	
This returns OK but the IDispatch pointer returned from QuerySongs does not seem to be an iterator. Your example calls get_Iterator, is something a c++ iterable object?

I feel I must be very close to the solution. Any suggestions gratefully received.

Re: Using the COM interface with VS2017 and plain C++

by Peke » Wed Jun 20, 2018 9:10 pm

Maybe something like

Code: Select all

ISDBDatabase* pDatabase;
	pSDB->get_Database(&pDatabase);
	ISDBSongIterator* pSDBIterator
	get_Iterator(&pDatabase->QuerySongs());
Forgive me if I'm wrong this is not my stronger side.

Also do not extract check EOF result and if NOT Get ITEM and Call NEXT like with pPlayer->Play() til you get what you want or EOF.

Re: Using the COM interface with VS2017 and plain C++

by dplummer » Wed Jun 20, 2018 5:12 pm

Hi again,

I had really hoped that I could work this out for myself but I have failed to get a result from QuerySongs with the c++ interface.

I have successfully accessed the interface and can control the player. However I have been reading as much background as I can and beating my head against a brick wall but am getting nowhere.

QuerySongs runs and returns an IDispatch object pointer. The documentation says that the it should return a SongIterator object but I cannot discover how to either extract SongIterator from the IDispatch or to get it from the ISDBDatabase object. This works from Python with WIN32COM so I think I must have a fundamental misunderstanding of something.

If anyone is able to point me in a helpful direction I would really appreciate it.

Thanks in advance

Re: Using the COM interface with VS2017 and plain C++

by dplummer » Tue Jun 12, 2018 11:15 am

Many thanks petrCBR,

With a bit of tweaking that did the trick. Here is a working fragment:

Code: Select all

	CoInitialize(NULL);
	ISDBApplication *pSDB;
	HRESULT hr = CoCreateInstance(CLSID_SDBApplication, NULL, CLSCTX_LOCAL_SERVER, IID_ISDBApplication, reinterpret_cast<void**>(&pSDB));
	if (hr!=S_OK) {
		printf("Failed to create instance: %x\n", hr);
		return;
	}

	// Keep opened instance running after disconnect
	pSDB->put_ShutdownAfterDisconnect(false);    

	// Start the current track playing
	ISDBPlayer* pPlayer;
	pSDB->get_Player(&pPlayer);
	pPlayer->Play();
Best regards

Dave

Re: Using the COM interface with VS2017 and plain C++

by PetrCBR » Mon Jun 11, 2018 5:03 am

Probably something like this could work ?

Code: Select all

ISDB *pSDB;
hr = CoCreateInstance(CLSID_SDB, NULL, CLSCTX_INPROC_SERVER, IID_SDB, reinterpret_cast<void**>(&pSDB));

Using the COM interface with VS2017 and plain C++

by dplummer » Sat Jun 09, 2018 12:26 pm

All,

I know that the COM interface is deprecated and also appreciate that C++ is rather long in the tooth but I am where I am, trying to port some existing Python code that works with win32com into an existing c++ console application developed under Visual Studio 2017.

So far I have generated an IDL file from MediaMonkey.exe (4.1.20) and (after addition of some forward definitions) got it to compile .h and .c files which I have added to my project.

My problem now is that I cannot work out how to instantiate an SDB object to start working with.

I was expecting something like: SongsDB::SDBApplication SDB = new SongsDB::SDBApplication();
But SongsDB is not recognised

I have also tried using #import on the MM executable but my .tld file is failing to compile because various terms (such as EOF) have been #defined elsewhere and generate errors.

If someone could give me some pointers please I would be very grateful.

Many thanks
Dave

Top