NO

Author Topic: COM objects in plain C...  (Read 13072 times)

CommonTater

  • Guest
COM objects in plain C...
« on: June 03, 2012, 08:26:50 PM »
Well known musician, hardware designer and C programmer Jeff Glatt has authored an 8 part series on using COM objects in plain C... I found it to be very helpful.  It's clearly written and loaded with examples.  If you haven't seen it yet, you can access the whole series from his page at The Code Project...
 
http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=88625
 
Thanks Jeff.
 
 

Offline Vortex

  • Member
  • *
  • Posts: 865
    • http://www.vortex.masmcode.com
Re: COM objects in plain C...
« Reply #1 on: June 03, 2012, 11:10:46 PM »
COM is very powerful but it can be very complicated too. Thanks for the tutorials.
Code it... That's all...

CommonTater

  • Guest
Re: COM objects in plain C...
« Reply #2 on: June 04, 2012, 12:22:41 AM »
COM is very powerful but it can be very complicated too. Thanks for the tutorials.

Well, since it seems my time has come to learn this I've been doing some searching for information... Thought I'd pass this one along.  I know Jeff from back in my "pro-sound" days so I trust it's mostly accurate.  If I find more, I'll pass them along as well...


czerny

  • Guest
Re: COM objects in plain C...
« Reply #3 on: March 27, 2013, 12:17:52 PM »
Hallo,

I have read the first two parts of 'COM in plain C' and build corresponding Pelles C projects. If anyone has problems with this, I can post them.

EdPellesC99

  • Guest
Re: COM objects in plain C...
« Reply #4 on: March 27, 2013, 03:56:31 PM »
Thanks Tater, for the lead for future interests for me !

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: COM objects in plain C...
« Reply #5 on: November 24, 2017, 02:26:45 PM »
Time pasts, but those tutorials are still valuable :)

A tiny example for testing IExample2 without COM registration.
Easier to develop similar one.
May the source be with you

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: COM objects in plain C...
« Reply #6 on: November 26, 2017, 01:49:45 AM »
Hi Timo,
Can you explain in a few words what the program does? Just curious...

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: COM objects in plain C...
« Reply #7 on: November 26, 2017, 11:46:54 AM »
That example loads IExample2.dll
 ask IClassFactory pointer using exported function DllGetClassObject()
 create object /CreateInstance IExample2 to the pointer pExample2
 release IClassFactory
 call methods/functions SetString() and GetString()
 finally release IExample2

In this way it's easier to develop functions and debug those.
Code: [Select]
int __cdecl main(void)
{
IClassFactory *pClassFactory;
HMODULE hModule = LoadLibrary(TEXT("iexample2\\IExample2.dll"));
if (!hModule) return 1;
HRESULT (WINAPI*DllGetClassObject)(REFCLSID,REFIID,LPVOID) =
(HRESULT(WINAPI*)(REFCLSID,REFIID,LPVOID))GetProcAddress(hModule, TEXT("DllGetClassObject"));
if (!DllGetClassObject) return 2;
HRESULT hr = DllGetClassObject(&CLSID_IExample2, &IID_IClassFactory, (void**)&pClassFactory);
printf("hr=%X\n", hr);
if (!hr) {
IExample2 *pExample2;
hr = pClassFactory->lpVtbl->CreateInstance(pClassFactory, NULL, &IID_IExample2, (void **)&pExample2);
pClassFactory->lpVtbl->Release(pClassFactory);
printf("hr=%X\n", hr);
BSTR bstr1 = SysAllocString(L"test");
pExample2->lpVtbl->SetString(pExample2, bstr1);
BSTR bstr2;
pExample2->lpVtbl->GetString(pExample2, &bstr2);
printf("%ls\n", bstr2);
SysFreeString(bstr2);
pExample2->lpVtbl->Release(pExample2);
}
return 0;
}

Hopefully we see something more in this thread.
Experts could fix code and tell us what other things have to care.

EDIT:
After dll debug next example:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
#pragma comment(lib, "ole32")
#pragma comment(lib, "oleaut32")
#include "IExample2.h"
void ErrorString(HRESULT errno);
int __cdecl main(void)
{
IExample2 *pExample2 = NULL;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(&CLSID_IExample2, NULL, CLSCTX_ALL, &IID_IExample2, (void**)&pExample2);
printf("hr=%X\n", hr);
if (!hr && pExample2) {
printf("hr=%X\n", hr);
BSTR bstr1 = SysAllocString(L"test");
pExample2->lpVtbl->SetString(pExample2, bstr1);
BSTR bstr2;
pExample2->lpVtbl->GetString(pExample2, &bstr2);
printf("%ls\n", bstr2);
SysFreeString(bstr2);
pExample2->lpVtbl->Release(pExample2);
} else ErrorString(hr);
CoUninitialize();
return 0;
}
void ErrorString(HRESULT errno)
{
#define BUFSIZE 1000
static TCHAR szMsgBuf[BUFSIZE];

FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL, errno
, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
, (LPTSTR) szMsgBuf, BUFSIZE
, NULL);
printf("%Xh %s\n", errno, szMsgBuf);
}
Registration-Free COM manifest
Code: [Select]
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity type="win32" name="IExample2Test.exe" version="1.0.0.0" />
  <file name="IExample2.dll">
    <comClass progid="IExample2.Test"
       clsid="{520F4CFD-61C6-4EED-8004-C26D514D3D19}"
       description="IExample2 Control" />
  </file>
</assembly>

EDIT: small tool to create manifest lines:
Code: [Select]
#define UNICODE
#define _UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
#include <tchar.h>
#include <stdio.h>

#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")

//int DumpTLib(WCHAR *szFileName)
int __cdecl wmain(int argc, wchar_t **argv)
{
LPTYPELIB pITypeLib;
WCHAR wsGuid[40];

if (!LoadTypeLibEx(argv[1], REGKIND_NONE, &pITypeLib))
{
BSTR bstrLib;
pITypeLib->lpVtbl->GetDocumentation(pITypeLib, -1, &bstrLib, 0, 0, 0);
TLIBATTR *pLibAttr;
pITypeLib->lpVtbl->GetLibAttr(pITypeLib, &pLibAttr);
StringFromGUID2(&pLibAttr->guid, wsGuid, sizeof(wsGuid));
_tprintf(_T("<file name=\"%ls\">\n<typelib tlbid=\"%ls\" />\n"),
argv[1], wsGuid);
pITypeLib->lpVtbl->ReleaseTLibAttr(pITypeLib, pLibAttr);
UINT tiCount = pITypeLib->lpVtbl->GetTypeInfoCount(pITypeLib);
for (UINT i = 0; i < tiCount; i++)
{
TYPEKIND TypeKind;
BSTR bstrName;
LPTYPEINFO pITypeInfo;
pITypeLib->lpVtbl->GetTypeInfoType(pITypeLib, i, &TypeKind);
pITypeLib->lpVtbl->GetDocumentation(pITypeLib, i, &bstrName, 0, 0, 0);
if (!pITypeLib->lpVtbl->GetTypeInfo(pITypeLib, i, &pITypeInfo))
{
TYPEATTR *pTypeAttr;
if (!pITypeInfo->lpVtbl->GetTypeAttr(pITypeInfo, &pTypeAttr))
{
if (TypeKind == TKIND_COCLASS) {
StringFromGUID2(&pTypeAttr->guid, wsGuid, sizeof(wsGuid));
//_tprintf(_T("<comClass clsid=\"%ls\" />\n"), wsGuid);
_tprintf(_T("<comClass clsid=\"%ls\" progid=\"%ls.%ls\"/>\n"),
wsGuid, bstrLib, bstrName);
}
pITypeInfo->lpVtbl->ReleaseTypeAttr(pITypeInfo, pTypeAttr);
}
pITypeInfo->lpVtbl->Release(pITypeInfo);
}
if (bstrName) SysFreeString(bstrName);
}
if (bstrLib) SysFreeString(bstrLib);
_tprintf(_T("</file>\n"));
}
return 0;
}
« Last Edit: November 28, 2017, 08:45:38 PM by TimoVJL »
May the source be with you

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: COM objects in plain C...
« Reply #8 on: July 01, 2018, 10:57:58 AM »
Hi Timo,
Just tried to build this project with the new Pelles C version, and it shows plenty of warnings.
Code: [Select]
Building DllMainStartup.obj.
Building IExample2.obj.
C:\PellesC\Timo\Timo\COM\iexample2\IExample2.c(209): warning #2030: '=' used in a conditional expression.
C:\PellesC\Timo\Timo\COM\iexample2\IExample2.c(222): warning #2071: Overflow or truncation in constant expression.
C:\PellesC\Timo\Timo\COM\iexample2\IExample2.c(229): warning #2030: '=' used in a conditional expression.
Building IExample2.dll.
POLINK: warning: Unrecognized keyword 'PRIVATE' in module-definition file 'C:\PellesC\Timo\Timo\COM\iexample2\IExample2.def'; ignored.
POLINK: warning: Unrecognized keyword 'PRIVATE' in module-definition file 'C:\PellesC\Timo\Timo\COM\iexample2\IExample2.def'; ignored.
Creating object: C:\PellesC\Timo\Timo\COM\iexample2\IExample2.exp
Creating library: C:\PellesC\Timo\Timo\COM\iexample2\IExample2.lib
Done.
It builds, but VBS complains that the ActiveX component cannot create the IExample2.object

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: COM objects in plain C...
« Reply #9 on: July 01, 2018, 12:20:06 PM »
That dll need a typelib and registeration for that :(
Use midl compiler from SDK to make typelib.

Those warnings, add !=0
Code: [Select]
if ((hr = loadMyTypeInfo())!=0) return(hr);cast with (ULONG)
Code: [Select]
return((ULONG)DISP_E_UNKNOWNINTERFACE);and remove or comment out that PRIVATE
May the source be with you