C++/WinRT: MIDL 3.0 type: Char - compile of generated code returns 'T must be WinRT type'. Is there a support usage? - c++-winrt

Using the idl source containing the MIDL 3.0 simple type Char:
namespace BrokenMIDL_Char
{
[default_interface]
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
MainPage();
Int32 MyProperty;
Char MyStationLetter_1;
//Char MyStationLetter_2;
//Char MyStationLetter_3;
}
}
And the supporting functions
wchar_t MyStationLetter_1()
{
throw hresult_not_implemented();
}
void MyStationLetter_1(wchar_t /*value*/)
{
throw hresult_not_implemented();
}
char16_t MyStationLetter_2()
{
throw hresult_not_implemented();
}
void MyStationLetter_2(char16_t /*value*/)
{
throw hresult_not_implemented();
}
char MyStationLetter_3()
{
throw hresult_not_implemented();
}
void MyStationLetter_3(char /*value*/)
{
throw hresult_not_implemented();
}
Results in an error
T must be a WinRT type
My understanding was that the MIDL 3.0 types are the definition the WinRT types.
The MIDL compiler emits:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
template<typename TDeclaringType, typename TValue>
void SetValueTypeMember_MyStationLetter_1(
::winrt::Windows::Foundation::IInspectable const& instance,
::winrt::Windows::Foundation::IInspectable const& value)
{
instance.as<TDeclaringType>().MyStationLetter_1(::winrt::unbox_value<TValue>(value));
}

During testing, I have a solution you could make a try.
You could open the Property tab > Properties > Configuration Properties > C/C++ > Language, find Treat Wchar_t As Built in Type property and select the No(/Zc:wchar_t-) option. Then, try to build your project.

Related

WinRT C++ component with non primitive function return types fails to compile/build

The below program works fine while having functions with primitive return type functions specifically the Pop function defined below works and I'm able to build properly, but when I build the solution with a function having non primitive return type as in PopC like below project doesn't build, but definitions are syntatically correct and I'm able to see the types being referred properly with proper namespace definitions in pch.h file.
Have defined the below code in the StreamSamplePool.idl file,
namespace WinRTComponent
{
[default_interface]
runtimeclass StreamSamplePool
{
StreamSamplePool();
Int32 MyProperty;
// MediaStreamSample PopC();
Int32 Pop();
}
}
And inside the StreamSamplePool.cpp file have defined the respective methods as follows
#include "pch.h"
#include "StreamSamplePool.h"
#include "StreamSamplePool.g.cpp"
#include <stack>
#include <queue>
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Foundation;
using namespace std;
//using namespace Platform;
using namespace winrt::Windows::Media::Core;
namespace winrt::WinRTComponent::implementation
{
int32_t StreamSamplePool::MyProperty()
{
throw hresult_not_implemented();
}
int32_t StreamSamplePool::Pop()
{
return int32_t();
}
//MediaStreamSample StreamSamplePool::PopC()
//{
// MediaStreamSample sample = MediaStreamSample::CreateFromBuffer(NULL,
//TimeSpan());
// //sample.Processed += OnSampleProcessed;
// return sample;
//}
void StreamSamplePool::MyProperty(int32_t /* value */)
{
throw hresult_not_implemented();
}
}
And have defined the following code inside StreamSamplePool.h
namespace winrt::WinRTComponent::implementation
{
struct StreamSamplePool : StreamSamplePoolT<StreamSamplePool>
{
StreamSamplePool() = default;
int32_t Pop();
//MediaStreamSample PopC();
int32_t MyProperty();
void MyProperty(int32_t value);
};
}
namespace winrt::WinRTComponent::factory_implementation
{
struct StreamSamplePool : StreamSamplePoolT<StreamSamplePool,
implementation::StreamSamplePool>
{
};
}
Error info
Error MIDL2011 [msg]unresolved type declaration [context]: WinRTComponent.MediaStreamSample [ Procedure 'PopC' ( RuntimeClass
'WinRTComponent.StreamSamplePool' ) ] WinRTComponent D:\Prithvi\Work\WinRTComponent\StreamSamplePool.idl 9
Compiler output
1>D:\...\StreamSamplePool.idl(9): error MIDL2011: [msg]unresolved type declaration [context]: WinRTComponent.MediaStreamSample [ Procedure 'PopC' ( RuntimeClass 'WinRTComponent.StreamSamplePool' ) ]
1>Done building project "WinRTComponent.vcxproj" -- FAILED.
The issue can be reduced to the following IDL file:
namespace WinRTComponent
{
[default_interface]
runtimeclass StreamSamplePool
{
StreamSamplePool();
MediaStreamSample PopC();
}
}
Compiling this using a default-generated C++/WinRT Component project produces the following error:
1>C:\...\StreamSamplePool.idl(7): error MIDL2011: [msg]unresolved type declaration [context]: WinRTComponent.MediaStreamSample [ Procedure 'PopC' ( RuntimeClass 'WinRTComponent.StreamSamplePool' ) ]
It contains all the information required to resolve the issue. In particular it's naming the error ("unresolved type declaration"), and the procedure affected ("PopC"). To solve this you'll have to provide the fully-qualified type name in the IDL file, i.e.
namespace WinRTComponent
{
[default_interface]
runtimeclass StreamSamplePool
{
StreamSamplePool();
Windows.Media.Core.MediaStreamSample PopC();
}
}
With that done, go to the "Generated Files\sources" directory under the project root, and copy the respective parts of the "StreamSamplePool.h" and "StreamSamplePool.cpp" files that the build system generated to your source files.

Immediate Access Violation when debugging Windows.Devices.Sensors project in Windows 7

I have a large solution with 50+ unmanaged projects in it. I have recently added a project with managed code in it to the solution. The managed code accesses Windows.Devices.Sensors in a .NET dll. This dll is eventually wrapped by unmanaged code and called from another unmanaged project.
My problem is that I get the following access violation before main() even executes.
Unhandled exception at 0x744b8ea0 in myApplication.exe: 0xC0000005: Access violation.
Managed code:
#using <Windows.winmd>
using namespace Windows::Devices::Sensors;
#include <math.h>
namespace TabletSensors
{
namespace NET
{
public ref class DotNetDllClass
{
public:
DotNetDllClass()
{
Initialization();
}
~DotNetDllClass()
{
}
float* GetQuaternion()
{
OrientationSensorReading^ reading = _orientation->GetCurrentReading();
if( reading != nullptr )
{
float* quat = new float[4];
quat[0] = reading->Quaternion->X;
quat[1] = reading->Quaternion->Y;
quat[2] = reading->Quaternion->Z;
quat[3] = reading->Quaternion->W;
return quat;
}
else
{
return NULL;
}
}
private:
void Initialization()
{
_orientation = OrientationSensor::GetDefault();
if( _orientation != nullptr )
{
_orientation->ReportInterval = 16;
}
else
{
// not good ... throw exception or something
}
}
OrientationSensor^ _orientation;
};
}
}
Wrapper header file:
namespace TabletSensors
{
namespace NETWrapper
{
class DLLEXPORT_SENSORS WrapperClass
{
public:
__stdcall WrapperClass();
__stdcall ~WrapperClass();
float* __stdcall GetQuaternion();
};
}
}
Wrapper cpp file:
#define MIXSENSORS_BUILD
#include <gcroot.h>
#include "DotNetWrapper.h"
#include "DotNetDll.h"
using namespace TabletSensors::NETWrapper;
using namespace TabletSensors::NET;
static gcroot<TabletSensors::NET::DotNetDllClass^> Sensors = nullptr;
static System::UInt16 refCount = 0;
#pragma managed
inline TabletSensors::NET::DotNetDllClass^ GetSensors(void)
{
return (TabletSensors::NET::DotNetDllClass^)Sensors;
}
void Init()
{
++refCount;
if(GetSensors() == nullptr)
{
Sensors = gcnew TabletSensors::NET::DotNetDllClass();
}
}
void CleanUp()
{
if( refCount > 0 )
{
--refCount;
}
}
float* GetQuaternion_()
{
return Sensors->GetQuaternion();
}
#pragma unmanaged
TabletSensors::NETWrapper::WrapperClass::WrapperClass()
{
Init();
}
TabletSensors::NETWrapper::WrapperClass::~WrapperClass()
{
CleanUp();
}
float* TabletSensors::NETWrapper::WrapperClass::GetQuaternion()
{
float* x = new float[4];
return GetQuaternion_();
}
#pragma managed
Unmanaged project referencing my wrapper class:
#include "DotNetWrapper.h"
.
.
.
void UnmanagedProject::Update()
{
// if this line is present, I get an access violation without hitting any breakpoints.
TabletSensors::NETWrapper::WrapperClass _tabletSensors;
.
.
.
}
Since the managed code is trying to access Tablet Sensors I understand why it doesn't work on my Windows 7 desktop. What I don't understand it why it won't even allow me to debug my code at all. No breakpoints are hit before the Access Violation occurs.
What I would really like to figure out is how to use exception handling or #ifdefs to keep this crash from happening. But I have had very little luck.
Any ideas?
The fix is to Delay Load the managed DLL. The allows the application to run until that DLL is explicitly called. Thanks to Ben Voight for his answer here: https://stackoverflow.com/a/28467701/1454861

MFC DLL: class object value is not persisting throughout the exported call

I have written MFC dll having 3 methods are exported. I have declared class object as global and initialized it in first method then second and third method use and process it.
Issue is that class obeject's value is not getting persisting throughout the file. when second or third method gets call from C# client application, class
object value is getting NULL.
Could anybody tell me why this is happening! I have tried this same scnaerio in another application but this issue is not reproduced.
Code:
Interface File:
#include "StdAfx.h"
#define DLLEXPORT __declspec(dllexport)
using namespace nsAnalyzer;
static CWindowsAnalyzer *pWindowsAnalyzer = NULL;
extern "C" DLLEXPORT void Init( const wchar_t *sCurrentUserDataDir,
const wchar_t *sMachineName,
const wchar_t *sMacId )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
nsAnalyzer::CWindowsAnalyzer *pWindowsAnalyzer = new CWindowsAnalyzer( CString(sCurrentUserDataDir),
CString(sMachineName),
CString(sMacId) );
if(pWindowsAnalyzer)
{
pWindowsAnalyzer->Init();
}
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Init: "<<e.what()<<endl;
}
}
extern "C" DLLEXPORT bool Analyze()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
bool bResult = false;
try
{
if(pWindowsAnalyzer->ConsolidateRawActivities())
{
cout<<"ConsolidateRawActivities succeed"<<endl;
bResult = true;
}
else
{
cout<<"ConsolidateRawActivities failed"<<endl;
bResult = false;
}
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Analyze: "<<e.what()<<endl;
}
return bResult;
}
extern "C" DLLEXPORT void Dispose()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
try
{
// Disponse windows analyzer
if(pWindowsAnalyzer)
{
delete pWindowsAnalyzer;
}
// Dispose Logger
CLogger::DisposeInstance();
}
catch(const std::exception& e)
{
cout<<"Error: Exception occured in Dispose: "<<e.what()<<endl;
}
}

SFML Input system problem

So I was porting my game engine from SDL to SFML, and now I have a problem with my input system.
Input.h
#ifndef BULLWHIP_INPUT_H
#define BULLWHIP_INPUT_H
#include
class bc_Input
{
public:
bool bm_KeyHit(sf::Key::Code key);
bool bm_KeyDown(sf::Key::Code key);
int bm_MouseX();
int bm_MouseY();
void bm_init(sf::RenderWindow app);
private:
sf::RenderWindow App;
const sf::Input& input;
};
#endif
Input.cpp
#include "Input.h"
bool bc_Input::bm_KeyDown(sf::Key::Code key)
{
return in.IsKeyDown(key)
}
bool bc_Input::bm_KeyHit(sf::Key::Code key)
{
sf::Event event;
while(App.GetEvent(event) && event.Type == sf::Event::KeyPressed)
{
switch(event.Key.Code)
{
case key: return true; break;
default:
break;
}
}
}
void bc_Input::bm_init(sf::RenderWindow app)
{
App = app;
in = App.GetInput();
}
int bc_Input::bm_MouseX()
{
return in.GetMouseX();
}
int bc_Input::bm_MouseY()
{
return in.GetMouseY();
}
I get these errors from this:
C:\c++\sdl\bullwhip\lib\Bullwhip\/Input.h:15: error: 'bc_Input::App' cannot appear in a constant-expression
C:\c++\sdl\bullwhip\lib\Bullwhip\/Input.h:15: error: '.' cannot appear in a constant-expression
C:\c++\sdl\bullwhip\lib\Bullwhip\/Input.h:15: error: a function call cannot appear in a constant-expression
C:\c++\sdl\bullwhip\lib\Bullwhip\/Input.h:15: error: ISO C++ forbids initialization of member 'input'
C:\c++\sdl\bullwhip\lib\Bullwhip\/Input.h:15: error: making 'input' static
C:\c++\sdl\bullwhip\lib\Bullwhip\/Input.h:15: error: invalid in-class initialization of static data member of non-integral type 'sf::Input&'
c:\program files (x86)\codeblocks\mingw\bin../lib/gcc/mingw32/4.4.0/../../../../include/SFML/System/NonCopyable.hpp:57: error: 'sf::NonCopyable::NonCopyable(const sf::NonCopyable&)' is private
c:\program files (x86)\codeblocks\mingw\bin../lib/gcc/mingw32/4.4.0/../../../../include/SFML/Window/Window.hpp:56: error: within this context
You're calling the copy constructor here:
void bc_Input::bm_init(sf::RenderWindow app)
{
App = app;
in = App.GetInput();
}
Note one of your error messages:
error: 'sf::NonCopyable::NonCopyable(const sf::NonCopyable&)
In order to avoid this problem, you should use an actual constructor for your sf::Input object along with an initialization list.
Alternatively, if you've already initialized a sf::RenderWindow in a higher subsystem (as is likely the case), simply changing your member variable App to a reference should do the trick.
//header
sf::RenderWindow& App;
...
//source
void bc_Input::bm_init(sf::RenderWindow& app)
{
App = app;
in = App.GetInput();
}

C++/CLI, "constant" reference to a tracking handle

I have spotted something like this in code:
void foo(IList<int>^ const & list ) { ... }
What does this ^ const& mean? I looked in the C++/CLI specification, but found no comments on making constant tracking references, nor the ^& combo.
Is this legal?
This code was probably written by a C++ programmer that used common C++ idiom to write C++/CLI. It is quite wrong, passing a reference to tracking handle is only possible if the handle is stored on the stack. It cannot work if the passed List<> reference is stored in a field of an object on the heap, the garbage collector can move it and make the pointer invalid. The compiler will catch it and generate an error. The ^ is already a reference, no additional reference is needed.
Without the reference, the const keyword doesn't make a lot of sense anymore either. Not that it ever did before, the CLR cannot enforce it. Not that this mattered much here, this code could not be called from any other .NET language. They won't generate a pointer to the tracking handle.
Just fix it, there's little point in keeping bad code like this:
void foo(IList<int>^ list ) { ... }
Example of code that shows that the reference cannot work:
using namespace System;
using namespace System::Collections::Generic;
ref class Test {
public:
IList<int>^ lst;
void foo(IList<int> const &list) {}
void wontcompile() {
foo(lst); // C3699
IList<int>^ okay;
foo(okay);
}
};
It's a reference which is constant to a tracking handle.
It allows you to pass the handle by reference instead of by value. Presumably the author thinks it's more efficient than copying the handle.
If the author meant to make the handle constant he should have used either of
Method(TestClass const ^ const & parameter)
Method(TestClass const^ parameter)
Or alternatively
Method(TestClass const^& parameter) - but the caller must const up the handle first
with
TestClass const^ constHandle = nonConstHandle
An example of each:
// test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
ref class TestClass
{
public:
void setA(int value)
{
a = value;
}
TestClass() :
a(10)
{
}
private:
int a;
};
class TakesHandle
{
public:
void methodX1(TestClass const ^ const & parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX2(TestClass const^ parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX3(TestClass const^& parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TakesHandle takes;
TestClass ^ test1 = gcnew TestClass();
// compiles
takes.methodX1(test1);
// compiles
takes.methodX2(test1);
TestClass const ^ constHandle = test1;
takes.methodX3(constHandle);
return 0;
}