What should I do for warning C26800? - c++-winrt

I have a method in a C++/WinRT component.
It produces the code analysis warning C26800.
The method is an async coroutine.
It returns an IAsyncOperation of a projected defined in a MIDL file.
It takes as a parameter an AudioGraph object which is a projected type from "Windows.Media.Audio.h".
The parameter is declared as "AudioGraph graph", not "AudioGraph const& graph" so that it is copied and not referenced.
But when I call a method on it, the code analysis reports a C26800 warning.
I can't figure what to do with this warning. Can I safely ignore it or should I change my code ?
Here is the code for the method :
IAsyncOperation<CompositeInstrument> CompositeInstrument::LoadAsync(AudioGraph graph)
{
MediaSource mediaSource{ MediaSource::CreateFromStream(waveStream, L"audio/x-wav") };
// the following line produces warning C26800: Utilisation d'un objet déplacé : ''graph'' (lifetime.1)
CreateMediaSourceAudioInputNodeResult result{ co_await graph.CreateMediaSourceAudioInputNodeAsync(mediaSource) };
if (result.Status() != MediaSourceAudioInputNodeCreationStatus::Success)
{
// etc...
}
// etc...
co_return compositeInstrument;
}

It was a bug in Visual Studio.
It has been fixed in VS 16.10.

Related

C++/WinRT: CoreApplication::Run(IFrameworkViewSource const&) is throwing E_INVALIDARG

I'm trying to figure out why at this point in the code I'm getting an E_INVALIDARG hresult:
// main.cpp
class App : public implements<App, IFrameworkView>
{
// stuff ...
};
class AppFactory : public implements<AppFactory, IFrameworkViewSource>
{
public:
IFrameworkView CreateView()
{
return make<App>();
}
};
int WINAPI wWinMain(
_In_ HINSTANCE,
_In_ HINSTANCE,
_In_ LPWSTR,
_In_ int)
{
init_apartment();
auto vpf = make<AppFactory>();
CoreApplication::Run(vpf); // <-- throwing E_INVALIDARG somewhere inside CoreApplication::Run
uninit_apartment();
return S_OK;
}
I'd have expected a compile error if I didn't do something required by a class inheriting implements<AppFractory, IFrameworkViewSource>, but as far as I know I'm checking (static) boxes.
fwiw the exception is triggered here:
// Windows.ApplicationModel.Core.h
template <typename D> auto consume_Windows_ApplicationModel_Core_ICoreApplication<D>::Run(winrt::Windows::ApplicationModel::Core::IFrameworkViewSource const& viewSource) const
{
check_hresult(WINRT_IMPL_SHIM(winrt::Windows::ApplicationModel::Core::ICoreApplication)->Run(*(void**)(&viewSource)));
}
The thing inside check_result(...) is what's returning E_INVALIDARG, and subsequently triggering the exception. I'm not a super expert at writing windows applications, largely still in the "copy the template and hope it works while trying to understand something" phase. If there's some kind of tool I should be using to understand what the actual argument I'm passing is that is invalid, I'd appreciate some kind of pointer. I would think if I'm not passing the correct thing here, the strong type check of the argument would trigger a compile error and I'd have an opportunity to address the issue.
Honestly I'm lost here, would appreciate a hint towards where to look to resolve my issue. Thank you.
Update:
Don't know if this is relevant but in the Output tab in VS a line prints out:
Exception thrown at 0x00007FFA6D9A4FD9 (KernelBase.dll) in MyProgram.exe: WinRT originate error - 0x80070057 : 'serverName'.
I have no idea what this is... "serverName"? I don't even see a mention of this in the CoreApplication::Run docs.

Pass callbacks with managed parameters and return types between managed and unmanaged C++

I am writing a native C++ project with a managed C++ wrapper that can receive and invoke callbacks from C#. The managed side should be able to retrieve back that callback and trigger on the managed environment as well.
The signature of the said callback is:
// Native C++
typedef EvaluateResult (*NativeFunction) (std::vector<EvaluateResult> args);
// Managed C++ wrapper
delegate EvaluateResultWrapper^ ManagedFunction (List<EvaluateResultWrapper^> args);
The EvaluateResultWrapper is the managed wrapper class for the native class EvaluateResult. The conversion between the EvaluateResult is:
EvaluateResult result;
EvaluateResultWrapper^ wrapper = gcnew EvaluateResultWrapper (result);
result = EvaluateResult (*wrapper.original);
I want to implement the constructor EvaluateResultWrapper::EvaluateResultWrapper (ManagedFunction^ func) that can roughly do the following:
// NOTE: Pseudo code
void EvaluateResultWrapper::EvaluateResultWrapper (ManagedFunction^ func) {
this->func = func; // Store the func as a member to avoid GC
// original is the pointer to the EvaluateResult that this object is wrapping around
this->original = new EvaluateResult ([&func](std::vector<EvaluateResult> args) -> EvaluateResult {
List<EvaluateResultWrapper^>^ argsList; // Convert args from vector to List. Assuming it is done under the hood
EvaluateResultWrapper^ wrapper = func->Invoke (argsList); // Invoke the managed callback
return EvaluateResult (wrapper.GetOriginal ()); // Convert the managed result to the native counterpart
});
}
I know the above code will not work, but the idea I should be able to wrap the managed callback with codes that able to do conversion of both the callback arguments and return types, so that it is native friendly.
Ideally, I can also do the other way around (not important)
// NOTE: Pseudo code
ManagedFunction^ EvaluateResultWrapper::GetFunction (ManagedFunction^ func) {
// if the callback is set by the managed side, return the same callback back
if (this->func != nullptr) return this->func;
// Otherwise, the callback is a native one
NativeFunction nativeFunc = this->original->GetFunction ();
return gcnew ManagedFunction ([&nativeFunc] (List<EvaluateResultWrapper^>^ args) -> EvaluaResultWrapper {
std::vector argsList; // Convert the args from List back to vector. Assuming it is done under the hood
EvaluateResult result = nativeFunc (argsList); // Invoke the native function
return gcnew EvaluateResultWrapper (result); // Convert the native result into the managed one
});
}
I wonder whether this can be done?
A little bit of context: I am writing an external scripting system on native C++ for our games (similar to Lua scripting). The EvaluateResult is a class representing an evaluation result of any statement. It is basically a value coupled with the type. The type can be either number, boolean, string, array, object, or in this case: function callback.
The function callback can be either set within the native C++ (when the interpreter pass the user-defined function in the scripts) or a function set by the host (managed side).
The idea is the host (C# side) should be able to define and set functions into the memory (defining print() function to print into the host console for example). The callback is wrapped as an EvaluateResult class before storing into the the scripting memory.
For inspection purpose, C# side must be able to get the function callback. Therefor, the ability to get the function is nice to have (but not important, since I can always instruct the native side to execute the function for me)

Mono and Extension Methods with MonoDevelop 2.8.5

I have written a unit test with MD 2.8.5 in a project that includes System.Core and with build target Mono/.NET 3.5. I really like the Assert.Throws of the newer NUnit, so decided to write an extension method for it. I created a new file with this as its content in the same namespace as the test. Can anyone see my error?
public delegate void TestDelegate();
public static class AssertThrows
{
public static T Throws<T>(this Assert assert, TestDelegate td)
where T : Exception
{
try
{
td();
}
catch(T e)
{
return e;
}
catch
{
throw new AssertionException("Wrong exception type.");
}
throw new AssertionException("Did not throw an error.");
}
}
MonoDevelop "sees" the extension method through its code completion. However, the compiler reports:
Performing main compilation...
/Users/shamwow/dev/EngineTests.cs(19,37): error CS0117:
`NUnit.Framework.Assert' does not contain a definition for `Throws'
/Applications/MonoDevelop.app/Contents/MacOS/lib/monodevelop/AddIns/NUnit/nunit.framework.dll (Location of the symbol related to previous error)
Build complete -- 1 error, 0 warnings
(I know MD and Mono are not the same.)
I assume you're trying to use it just as:
Assert.Throws<FooException>(() => ...);
Extension methods don't work like that - they appear to be instance methods on the extended type. As you won't have an instance of Assert, you can't call your extension method like that.

Managed C++, Object reference not set to an instance of an object

I've run into this problem before, but never in a situation like this. I'm completely confused. As the question states, I'm getting the runtime error "Object reference not set to an instance of an object." Using the debugger tools, I think I've pinpointed the problem to this line:
dataFileLocation = path;
The entire function is here:
void DATReader::SetPath(String^ path)
{
if(!File::Exists(path))
{
MessageBox::Show( "DATReader (missing dat file: \n"+path+"\n )", "Error", MessageBoxButtons::OK, MessageBoxIcon::Exclamation);
return;
}
dataFileLocation = path;
}
dataFileLocation is declared here, but nothing is assigned to it:
ref class DATReader
{
private:
System::String^ dataFileLocation;
// ...
}
Now I know the reason I'm getting the error is because dataFileLocation is assigned to nothing. But I'm having problems assigning it. When I add = 0; to it, it won't build because its a ref class. When I try to assigned it to = 0; in the constructor, it yells at me for trying to convert it from a System::String^ to an int. If I assign it to a = gcnew String(""); it builds, but throws the same runtime exception.
I don't get it, am I reading the debugger wrong, and this isn't the source of the problem at all? I've just started to use managed code recently, so I'm confused :\
You may want to check and make sure your DATReader object isn't null as well It may be throwing the exception at your DATReader.SetPath() call.
This is a nicety in C# that's missing in C++/CLI. C# generates code that ensures this can never be null. Easily seen in the debugger by setting a breakpoint on the method and inspecting "this". Here's an example program that reproduces the exception:
#include "stdafx.h"
using namespace System;
ref class Example {
String^ dataFileLocation;
public:
void SetPath(String^ path) {
dataFileLocation = path; // Set breakpoint here and inspect "this"
}
};
int main(array<System::String ^> ^args)
{
Example^ obj /* = gcnew Example */;
obj->SetPath("foo");
return 0;
}
Remove the /* */ comments to fix. Fix your code by looking at the call stack to find the method that forgot to instantiate the object.
Managed C++ uses nullptr for null references. So you can check:
if (path == nullptr) { ... }
or use:
if (!String::IsNullOrEmpty(path))

How to register component interface in wxwebconnect?

I'm doing an experiment with wxWebConnect test application, incorporating the xpcom tutorial at "http://nerdlife.net/building-a-c-xpcom-component-in-windows/"
I adapt MyComponent class as necessary to compile together with testapp.exe (not as separate dll), and on MyApp::OnInit I have the following lines:
ns_smartptr<nsIComponentRegistrar> comp_reg;
res = NS_GetComponentRegistrar(&comp_reg.p);
if (NS_FAILED(res))
return false;
ns_smartptr<nsIFactory> prompt_factory;
CreateMyComponentFactory(&prompt_factory.p);
nsCID prompt_cid = MYCOMPONENT_CID;
res = comp_reg->RegisterFactory(prompt_cid,
"MyComponent",
"#mozilla.org/mycomp;1",
prompt_factory);
Those lines are copied from GeckoEngine::Init(), using the same mechanism to register PromptService, etc. The code compiles well and testapp.exe is running as expected.
I put javascript test as below :
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const cid = "#mozilla.org/mycomp;1";
obj = Components.classes[cid].createInstance();
alert(typeof obj);
// bind the instance we just created to our interface
alert(Components.interfaces.nsIMyComponent);
obj = obj.QueryInterface(Components.interfaces.nsIMyComponent);
} catch (err) {
alert(err);
return;
}
and get the following exception:
Could not convert JavaScript argument arg 0 [nsISupport.QueryInterface]
The first alert says "object", so the line
Components.classes[cid].createInstance()
is returning the created instance.
The second alert says "undefined", so the interface nsIMyComponent is not recognized by XULRunner.
How to dynamically registering nsIMyComponent interface in wxWebConnect environment ?
Thx
I'm not sure what is happening here. The first thing I would check is that your component is scriptable (I assume it is, since the demo you copy from is). The next thing I would check is whether you can instantiate other, standard XULRunner components and get their interface (try something like "alert('Components.interfaces.nsIFile');" - at least in my version of wxWebConnect this shows an alert box with string "nsIFile".
Also, I think it would be worth checking the Error Console to make sure there are no errors or warnings reported. A magic string to do that (in Javascript) is:
window.open('chrome://global/content/console.xul', '', 'chrome,dialog=no,toolbar,resizable');