I have a library written in C++ and I want to use structures from it when declaring interfaces in IDL file. Here is the sample:
service.idl
import "..//core//common_structures.h";
[
object,
uuid(13B01AEB-52EC-4546-BDE0-DE91B37337CE),
dual,
pointer_default(unique)
]
interface IDeviceManagement: IUnknown {
HRESULT GetSerialByIndex ([in] uint8_t id, [out] Serial *serial, [out, retval] VARIANT_BOOL *result);
};
Serial structure is defined in imported header under key_api namespace. When building everything goes ok until service_i.h is generated and the following error appears:
error C2061: syntax error : identifier 'Serial' ..\service\service_i.h
near these generated lines:
IDeviceManagement : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetSerialByIndex(
/* [in] */ uint8_t id,
/* [out] */ Serial *serial,
/* [retval][out] */ VARIANT_BOOL *result) = 0;
};
I think it's because of Serial is wrapped under the namespace and service_i.h doesn't know anything about it. One solution is just to get rid of namespace. Is there any variant when we can actually keep the namespace?
Related
I'm writing a com component using ATL 140, and use this macro in my component body
#define DECLARE_REGISTRY(class, pid, vpid, nid, flags)\
static HRESULT WINAPI UpdateRegistry(_In_ BOOL bRegister) throw()\
{\
return _Module.UpdateRegistryClass(GetObjectCLSID(), pid, vpid, nid,\
flags, bRegister);\
}
UpdateRegistry has a reference to _Module and it must be a CComModule, since only this class has the UpdateRegistryClass method. But per this doc, CComModule is deprecated. So should I declare _Module as my module and copy UpdateRegistryClass and paste to my module? Many thanks!
struct MyModule : CAtlExeModuleT<MyModule>
{
HRESULT WINAPI UpdateRegistryClass(...){...};
};
...
MyModule _Module;
After porting a project from visual studio to mingw. I am getting the following linker error
undefined reference to `g_Templates'
undefined reference to `g_cTemplates'
The code which it points to looks something like this
#include <tchar.h>
#endif // DEBUG
#include <strsafe.h>
#include <combase.h>
extern CFactoryTemplate g_Templates[];
extern int g_cTemplates;
HINSTANCE g_hInst;
DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
OSVERSIONINFO g_osInfo;
//
// an instance of this is created by the DLLGetClassObject entrypoint
// it uses the CFactoryTemplate object it is given to support the
// IClassFactory interface
class CClassFactory : public IClassFactory, public CBaseObject
{
private:
const CFactoryTemplate *const m_pTemplate;
...
public:
CClassFactory(const CFactoryTemplate *);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, __deref_out void ** ppv);
STDMETHODIMP_(ULONG)AddRef();
STDMETHODIMP_(ULONG)Release();
// IClassFactory
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out void **pv);
STDMETHODIMP LockServer(BOOL fLock);
// allow DLLGetClassObject to know about global server lock status
static BOOL IsLocked() {
return (m_cLocked > 0);
};
};
// --- COM entrypoints -----------------------------------------
//
// Call any initialization routines
//
void DllInitClasses(BOOL bLoading)
{
// traverse the array of templates calling the init routine
// if they have one
for (i = 0; i < g_cTemplates; i++) //<---------Cannot recognize this symbol
{
const CFactoryTemplate * pT = &g_Templates[i];
if (pT->m_lpfnInit != NULL)
{
(*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
}
}
}
....
....
I have been searching on this issue for a while and have not made any progress. It seems that that this symbol exists in strmbasd.lib (debug version) and is generated from DirectShow base classes. I generated strmbasd.lib using mingw64 however I am still getting this linker error. I wanted to know if there was any other approach I could try .
I have used Direct Show for Microsoft Visual C++. And found no such issue. Microsoft SDK provides the libraries and headers as well as the base classes. You may want to check the link. I haven't used MingW, so I don't know about the issue of MingW. You may try it in MSVC, MSDN provides some handful informations and references for Direct Show. Please check the previous link mentioned above.
Your including dllentry.cpp/dllsetup.cpp from DirectShow BaseClasses assumes that you develop a filter library and you are expected to define template symbols in your code (example) to satisfy linker.
If you don't see how your code is referencing factories, you can define fake array and g_cTemplates of zero to pass through, however eventually there is something that makes linker drag these symbols into output.
I'm writing a C++ application which imports a COM DLL as following,
#import "MyLib.dll" no_namespace, raw_interfaces_only
There is a problem using method '_GetObject' which is declared in the idl file like this,
[
object,
uuid(f022c0e0-1234-5678-abcd-c17d63954f4b),
dual,
nonextensible,
helpstring("IStorageProxy Interface"),
pointer_default(unique)
]
interface IStorageProxy : IDispatch
{
[hidden, helpstring("method _GetObject")]
HRESULT _GetObject(
[in] BSTR entryId,
[in] REFCLSID rclsid,
[in] REFIID riid,
[out, iid_is(riid), retval] IUnknown** stgObject);
};
But the generated tlh file has changed the types of the second and third parameters.
struct __declspec(uuid("f022c0e0-1234-5678-abcd-c17d63954f4b"))
IStorageProxy : IDispatch
{
//
// Raw methods provided by interface
//
virtual HRESULT __stdcall _GetObject (
/*[in]*/ BSTR entryId,
/*[in]*/ GUID * rclsid,
/*[in]*/ GUID * riid,
/*[out,retval]*/ IUnknown * * stgObject ) = 0;
};
As I'm coding against the original function signature (defined in the idl), so now the C++ code can't compile. I'm not sure why the types changed to 'GUID *'. Is there any way to stop the compiler from doing this?
No, that's normal. Both REFGUID and REFIID are just a typedef for GUID*. Same kind of idea as a HWND and HDC, typedefs for HANDLE. These typedefs catch mistakes in C++ code, they are not really appropriate in a type library that supplies typeinfo to many languages.
You could technically keep these typedefs but those types will then have to be defined in the type library as well so that the COM client knows what they mean. The component author would have to include WTypes.idl. That's probably too late by now, you can't do anything about it in a COM client.
I have a simple .IDL file (iface.idl) which describes an IUnknown based interface:
import "unknwn.idl";
[
uuid(80DFDD28-F033-431e-B027-CDD2078FC78A)
]
interface ISunPathCalc : IUnknown {
HRESULT Square([in, out] long * pVal);
HRESULT Cube([in, out] long * pVal);
};
When trying to compile it with midl /header iface.h iface.idl I'm getting 3 files: iface.h, iface_i.c and iface_p.c. The iface.h file contains a C++ declaration of ISunpathCalc interface:
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("80DFDD28-F033-431e-B027-CDD2078FC78A")
ISunPathCalc : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Square(
/* [out][in] */ long *pVal) = 0;
virtual HRESULT STDMETHODCALLTYPE Cube(
/* [out][in] */ long *pVal) = 0;
};
#else /* C style interface */
The remaining larger part of this file contains needless C stuff.
Q: Is there way to tell MIDL to generate only C++ part of header?
Is it possible to switch off generation of iface_i.c and iface_p.c files and to force MIDL to generate a C++ definition instead?
UPD1:
I tried to add [local] attribute as specified here:
[
local,
uuid(80DFDD28-F033-431e-B027-CDD2078FC78A)
]
but without any success.
Unfortunately there's no way of suppressing the C header generation.
One of my COM interface methods needs a parameter of user defined type as below:
[uuid(58ADDA77-274B-4B2D-B8A6-CAB5A3907AE7), object] //Interface
interface IRadio : IUnknown
{
...
HRESULT test_method2(someUDT* p2p_UDT);
...
};
How could fit the definition of the someUDT in the *.idl file? The someUDT type is a user defined struct.
Thanks.
Perhaps this helps you - it's german but the most interesting part is the code.
This is how a Struct is defined there:
[
uuid(62D33614-1860-11d3-9954-10C0D6000000),
version(1.0)
]
typedef struct TPerson
{
BSTR bstrFirstname;
BSTR bstrLastname;
long lAge;
TDepartment Dep;
} TPerson;
// Interface
This is how it is used later:
[
object,
uuid(FC126BCD-1EAC-11D3-996A-4C1671000000),
dual,
helpstring("ICMyUDT Interface"),
pointer_default(unique)
]
interface ICMyUDT : IDispatch
{
[id(1), helpstring("method PassUdtByRef")] HRESULT
PassUdtByRef([ref, in, out] TPerson* pPerson);
[id(2), helpstring("method ReturnUdt")] HRESULT ReturnUdt(
[out, retval] TPerson* pPerson);
[id(3), helpstring("method PassUdtByVal")] HRESULT
PassUdtByVal([in] VARIANT varPerson);
};
I think that you need to define the struct in the idl file. Something like:
[
uuid("..."),
v1_enum,
helpstring("Enum")
]
typedef enum MyEnum {
value_a,
value_b,
value_c
} MyEnum_t;