Cannot initialize unordered_map from int - visual-studio-2010

I've got a really strange problem. MSVC doesn't have initializer lists, so I've used a lambda to approximate them.
static const std::unordered_map<std::wstring, LexedFile::Token> reserved_words =
[]() -> std::unordered_map<std::wstring, LexedFile::Token> {
std::unordered_map<std::wstring, LexedFile::Token> retval;
// Do stuff with retval
return retval;
}();
MSVC throws a compiler error.
error C2440: 'initializing' : cannot convert from 'int' to
'std::tr1::unordered_map<_Kty,_Ty>'
Unless I'm quite blind, there's no "int" anywhere near this. I don't see what's wrong. Any suggestions?
Edit:
There's nothing funky about // Do stuff with retval, it's just a bunch of insertions, and this is a function-scope static variable in a lambda in a member function.
auto next = [&] {
static const std::unordered_map<std::wstring, LexedFile::Token> reserved_words =
[]() -> std::unordered_map<std::wstring, LexedFile::Token> {
std::unordered_map<std::wstring, LexedFile::Token> retval;
retval[L"namespace"] = LexedFile::Token::Namespace;
retval[L"for"] = LexedFile::Token::For;
retval[L"while"] = LexedFile::Token::While;
retval[L"do"] = LexedFile::Token::Do;
retval[L"switch"] = LexedFile::Token::Switch;
retval[L"case"] = LexedFile::Token::Case;
retval[L"default"] = LexedFile::Token::Default;
retval[L"try"] = LexedFile::Token::Try;
retval[L"catch"] = LexedFile::Token::Catch;
retval[L"auto"] = LexedFile::Token::Auto;
retval[L"type"] = LexedFile::Token::Type;
retval[L"break"] = LexedFile::Token::Break;
retval[L"continue"] = LexedFile::Token::Continue;
retval[L"return"] = LexedFile::Token::Return;
retval[L"static"] = LexedFile::Token::Static;
retval[L"sizeof"] = LexedFile::Token::Sizeof;
retval[L"decltype"] = LexedFile::Token::Decltype;
retval[L"if"] = LexedFile::Token::If;
retval[L"else"] = LexedFile::Token::Else;
return retval;
}();
if (stack.empty())
return;
std::wstring token(stack.begin(), stack.end());
stack.clear();
if (reserved_words.find(token) != reserved_words.end()) {
l.tokens.push_back(reserved_words.find(token)->second);
return;
}
l.tokens.push_back(LexedFile::Identifier);
};
The compiler will accept it if I use the constructor directly not initialization, which seems very strange. Probably a compiler bug.

Calling the constructor with () instead of using = works just fine, so I'm marking this one as a compiler error.

Related

How to use EnumProcesses in node-ffi

I was trying to use EnumProcesses with node-ffi. I got code below:
import ffi from 'ffi'
export const psapi = ffi.Library('psapi', {
EnumProcesses: ['bool', ['ulong', 'ulong', 'uint16*']]
})
export class Win32ProcessManager {
public async getProcessList () {
let lpidProcess = ref.alloc('ulong*')
const cb = 1024
const lpcbNeeded = ref.alloc('uint16*')
const res = psapi.EnumProcesses(lpidProcess, cb, lpcbNeeded)
const ulongSize = (ref as any).sizeof.ulong
const totalBytesReturned = lpcbNeeded.readInt16LE()
const processCount = totalBytesReturned / ulongSize
console.log(`processCount: ${processCount}`)
// ??? How to get the value from the lpidProcess?
return lpidProcess
}
}
I tried with ref.get but I encountered errors:
let processId = ref.get(array, 0, ref.types.ulong)
console.log(processId)
const pointerSize = (ref as any).sizeof.pointer
console.log(pointerSize)
let processId2 = ref.get(array, (ref as any).sizeof.pointer, ref.types.ulong)
console.log(processId2)
Errors:
RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to write outside buffer bounds
Anyone knows how to use node-ffi read the array data from dll?
Thanks #DrakeWu-MSFT, I finally got my code works, here are how they looks finally:
import ffi from 'ffi';
import ref from 'ref';
import ArrayType from "ref-array";
export const psapi = ffi.Library('psapi', {
EnumProcesses: ['bool', ['ulong*', 'ulong', 'uint16*']],
});
export class Win32ProcessManager {
public getProcessIdList (): number[] {
const processIdLength = 1024;
const ulongSize = (ref as any).sizeof.ulong;
const cb = processIdLength * ulongSize;
let processIdArray = ArrayType('ulong', processIdLength);
let lpidProcess = ref.alloc(processIdArray);
const lpcbNeeded = ref.alloc('uint16*');
const res = psapi.EnumProcesses(lpidProcess, cb, lpcbNeeded);
if (res) {
const totalBytesReturned = lpcbNeeded.readInt16LE();
const processCount = totalBytesReturned / ulongSize;
const processArray = (lpidProcess as any).deref();
let resultProcessArray: number[] = [];
for (let i = 0; i < processCount; i++) {
resultProcessArray.push(processArray[i]);
}
return resultProcessArray;
} else {
console.error(`Get process list failed with result from EnumProcess: ${res}`);
return [];
}
}
}
I was struggled with getting array data from the pointer, and that was wrong, as #DrakeWu-MSFT said in the comment, because I didn't allocate enough spaces for the buffer, no data can be write into that. With ref-array and a pointer to the array, it works like a charm.

Syntax help for creating a filter in aws ec2 describeinstance api call in c++

Using DescribeInstancesRequest (c++ sdk) to get response about a particular instance_id. I am having a problem constructing the filter.
I am adapting the example code provided by the aws-doc-sdk-examples c++ example code describe_instances.cpp. I have added code to filter the response to use a known valid (now hard coded) instance ID.
I have tried multiple variations to set up the filter, but the docs aren't clear to me about the "value pair" format for the filter.
Here is the complete code. It compiles just find, but always responds with the "Could not find: ..."
Please let me know what I am getting wrong with the filter syntax! (See commented section Filter an instance id)
Thanks
void Server::set_instance_info()
{
// Get server instance information via aws sdk
Aws::SDKOptions options;
Aws::InitAPI(options);
{
/* #TODO Make this a startup config value */
Aws::Client::ClientConfiguration clientConfig;
clientConfig.region = "us-west-2";
Aws::EC2::EC2Client ec2(clientConfig);
Aws::EC2::Model::DescribeInstancesRequest request;
// Filter an instance_id
Aws::EC2::Model::Filter filter;
filter.SetName("instance_id");
Aws::String filter_val{"Name=instance_id,Values=i-0e120b44acc929946"};
Aws::Vector<Aws::String> filter_values;
filter_values.push_back(filter_val);
filter.SetValues(filter_values);
Aws::Vector<Aws::EC2::Model::Filter> DIRFilter;
DIRFilter.push_back(filter);
request.SetFilters(DIRFilter);
auto outcome = ec2.DescribeInstances(request);
if (outcome.IsSuccess())
{
const auto &reservations =
outcome.GetResult().GetReservations();
for (const auto &reservation : reservations)
{
const auto &instances = reservation.GetInstances();
for (const auto &instance : instances)
{
Aws::String instanceStateString =
Aws::EC2::Model::InstanceStateNameMapper::GetNameForInstanceStateName(
instance.GetState().GetName());
Aws::String type_string =
Aws::EC2::Model::InstanceTypeMapper::GetNameForInstanceType(
instance.GetInstanceType());
Aws::String name = "Unknown";
const auto &tags = instance.GetTags();
auto nameIter = std::find_if(tags.cbegin(), tags.cend(),
[](const Aws::EC2::Model::Tag &tag)
{
return tag.GetKey() == "Name";
});
if (nameIter != tags.cend())
{
name = nameIter->GetValue();
}
Server::id_ = instance.GetInstanceId();
Server::name_ = name;
Server::type_ = type_string;
Server::dn_ = "Not implemented";
Server::ip_ = "Not implmented";
}
}
} else {
Server::id_ = "Could not find: " + filter_val;;
Server::name_ = "";
Server::type_ = "";
Server::dn_ = "";
Server::ip_ = "";
}
}
return;
}
I just couldn't get the filter to work. Any input would be appreciated. However, there is an alternate method using the WithInstanceIds member function. Reading the API docs is always a good idea!!
Here is the subroutine that works:
void Server::set_instance_info()
{
// Get server instance information via aws sdk
Aws::SDKOptions options;
Aws::InitAPI(options);
{
/* #TODO Make this a startup config value */
Aws::Client::ClientConfiguration clientConfig;
clientConfig.region = "us-west-2";
Aws::EC2::EC2Client ec2(clientConfig);
Aws::EC2::Model::DescribeInstancesRequest request;
/* #TODO Make this a startup config value */
const Aws::String instanceId{"i-0e120b44acc929946"};
Aws::Vector<Aws::String> instances;
instances.push_back(instanceId);
request.WithInstanceIds(instances);
auto outcome = ec2.DescribeInstances(request);
if (outcome.IsSuccess())
{
const auto &reservations =
outcome.GetResult().GetReservations();
for (const auto &reservation : reservations)
{
const auto &instances = reservation.GetInstances();
for (const auto &instance : instances)
{
Aws::String instanceStateString =
Aws::EC2::Model::InstanceStateNameMapper::GetNameForInstanceStateName(
instance.GetState().GetName());
Aws::String type_string =
Aws::EC2::Model::InstanceTypeMapper::GetNameForInstanceType(
instance.GetInstanceType());
Aws::String name = "Unknown";
const auto &tags = instance.GetTags();
auto nameIter = std::find_if(tags.cbegin(), tags.cend(),
[](const Aws::EC2::Model::Tag &tag)
{
return tag.GetKey() == "Name";
});
if (nameIter != tags.cend())
{
name = nameIter->GetValue();
}
Server::id_ = instance.GetInstanceId();
Server::name_ = name;
Server::type_ = type_string;
Server::dn_ = "Not implemented";
Server::ip_ = "Not implmented";
}
}
} else {
Server::id_ = "Could not find: "+ instanceId;
Server::name_ = "";
Server::type_ = "";
Server::dn_ = "";
Server::ip_ = "";
}
}
return;
}

JS: java.lang.Exception: Failed resolving method read on class android.media.AudioRecord

I'm trying to use android.media.AudioRecord to save audio, initialization is OK, startRecording() is also called without error, but when I start reading audio from the buffer I got error Failed resolving method read on class android.media.AudioRecord.
Here is the code:
const SAMPLE_RATE = 44100;
const RECORD_AUDIO = android.Manifest.permission.RECORD_AUDIO;
const AudioRecord = android.media.AudioRecord;
const AudioFormat = android.media.AudioFormat;
const MediaRecorder = android.media.MediaRecorder;
ngOnInit(): void {
this.bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
if (this.bufferSize == AudioRecord.ERROR || this.bufferSize == AudioRecord.ERROR_BAD_VALUE) {
this.bufferSize = SAMPLE_RATE * 2;
}
this.bufferSize = this.bufferSize * 10;
this.audioBuffer = new Array(this.bufferSize / 2);
if (!permissions.hasPermission(RECORD_AUDIO)) {
permissions.requestPermission(RECORD_AUDIO).then(() => {
this.createRecorder();
}, (err) => {
console.log('[BrowseComponent] ngOnInit, ', 'permissions error:', err);
});
}
else {
this.createRecorder();
}
}
createRecorder() {
this.record = new AudioRecord.Builder()
.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
.setAudioFormat(new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.setSampleRate(SAMPLE_RATE)
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
.build())
.setBufferSizeInBytes(this.bufferSize)
.build();
this.recordState = this.record && this.record.getState();
if (this.recordState != AudioRecord.STATE_INITIALIZED) {
console.error('[BrowseComponent] createRecorder, ', 'AudioRecord can\'t initialize, state:', this.recordState);
return;
}
console.log('[BrowseComponent] createRecorder, ', 'AudioRecord:', this.record);
}
startRecord() {
this.recording = true;
this.record.startRecording();
this.shortsRead = 0;
while (this.recording) {
const numberOfShort = this.record.read(this.audioBuffer, 0, this.bufferSize);
this.shortsRead += numberOfShort;
// Do something with the audioBuffer
}
}
startRecord() is called from (tap) button handler.
Any ideas what may be wrong?
I guess the problem is that you are passing JavaScript Array instead of the Java Primitive (short) typed Array, so the runtime is unable to identify a method that matches the given parameters.
Use Array.create method to typecast, refer the docs here for more details.

Handling exception in semantic actions

Consider the following parser:
class test
{
public:
static test from_string(const string &str); //throws!
};
template <typename Iterator = string::const_iterator>
struct test_parser : grammar<Iterator, test(), blank_type>
{
test_parser() : test_parser::base_type(query)
{
query = id[_val = phx::bind(&test::from_string, qi::_1)];
id = lexeme[*char_("a-zA-Z_0-9")];
}
rule<Iterator, test(), blank_type> query;
rule<Iterator, string(), blank_type> id;
};
I'd like to catch exceptions that test::from_string might throw and to fail the match on exception. I couldn't find direct way to do this, so I'm trying to use an "adapter" function that would accept the context explicitly. But how to access the context and how to attach such an action to the grammar? Please, see the questions within the code:
template<class Context>
void match_test(const string &attr, Context &context, bool &mFlag)
{
try
{
test t = test::from_string(attr);
// how do I access the context to put t into _val?
}
catch(...)
{
mFlag = false;
}
}
//...
test_parser() : test_parser::base_type(query)
{
query = id[?match_test<?>? /*how to instantiate and use the above semantic action?*/];
id = lexeme[*char_("a-zA-Z_0-9")];
}
Like the commenter said, use
query = id[
phx::try_ [
qi::_val = phx::bind(&test::from_string, qi::_1)
].catch_all [
qi::_pass = false
]
];
See it Live on Coliru
A version that compiles even with BOOST_SPIRIT_USE_PHOENIX_V3: Live on Coliru
query = id[
phx::try_ [
qi::_val = phx::bind(&test::from_string, qi::_1)
].catch_all [
qi::_pass = false
],
qi::_pass = qi::_pass // to appease the spirit expression compilation gods
];

How to get runtime-argument info from extression tree parameter array

Okay first to explain the rules:
I need a function that constructs a delegate matching any delegate type that encapsulates a body of which invokes a delegate of type (Object) (Object[] args) with 'args' containing all of the arguments passed to the original delegate during invocation.
My work so far:
delegate void TestDelegate(int x, int y);
delegate object TestDelegate2(object[] args);
static void Main(string[] sargs)
{
TestDelegate d = (TestDelegate)CreateAnonymousFromType(typeof(TestDelegate));
object ret = d.DynamicInvoke(2, 6);
if (ret != null) { Console.WriteLine(ret); }
Console.ReadKey();
}
static void SpecialInvoke(int x, int y)
{
Console.WriteLine("x: {0}\r\ny: {1}", x, y);
}
static Delegate CreateAnonymousFromType(Type type)
{
MethodInfo method = type.GetMethod("Invoke");
TestDelegate2 _delegate = new TestDelegate2(
delegate(object[] args)
{
Console.WriteLine("x: {0}\r\ny: {1}", args[0], args[1]);
return "This is the return";
});
var typeargs = CreateArgs(method.GetParameters());
var argindex = -1;
var tmp = Expression.Parameter(typeof(Object), "tmp");
var index = Expression.Parameter(typeof(int), "index");
var length = Expression.Constant(typeargs.Length);
var _break = Expression.Label("breakto");
var delegateargs = Expression.Parameter(typeof(object[]), "args");
return Expression.Lambda(
type,
Expression.Block(
new[] { tmp, index, delegateargs },
Expression.Assign(index, Expression.Constant(0)),
Expression.Assign(delegateargs, Expression.NewArrayBounds(typeof(Object), length)),
Expression.Loop(
Expression.IfThenElse(Expression.LessThan(index, length),
Expression.Block(
Expression.Assign(tmp, Expression.Convert(typeargs[++argindex], typeof(Object))),
Expression.Assign(Expression.ArrayAccess(delegateargs, index), tmp),
Expression.PostIncrementAssign(index)
),
Expression.Break(_break)
),
_break
),
Expression.Call(_delegate.Method, delegateargs)
),
typeargs
).Compile();
}
static ParameterExpression[] CreateArgs(ParameterInfo[] _params)
{
ParameterExpression[] ret = new ParameterExpression[_params.Length];
for (int i = 0; i < ret.Length; i++)
ret[i] = Expression.Parameter(_params[i].ParameterType, _params[i].Name);
return ret;
}
Now this SORTA works... I only get the value of typeargs[0] passed to the delegate "TestDelegate2" for both parameters x and y, the 'args' parameter at runtime is object[] { 2, 2 } and I can't for the life of me find a way to increment "argindex" inside the scope of the argument iteration... parameter count at compile time is indefinate.
Anybody know how I can solve this?
I've tried just copying the argument array using Expression.NewArrayInit(typeof(Object), typeargs) but that fails saying it can't use Int32 to initialize an array of Object
I've also tried this:
var arguments = Expression.Constant(typeargs);
And accessing the value of "arguments" at "index", however this produces the strings "x" and "y" .. apparently the names of the arguments and not their values.
This is honestly my first major attempt at using expression trees so any help.. no matter how little. Would be appreciated.
Thank you.
I think you were on the right track with Expression.NewArrayInit. You can fix the "An expression of type 'System.Int32' cannot be used to initialize an array of type 'System.Object'" error by using Expression.Convert to insert a conversion for each parameter:
var typeargs = CreateArgs(method.GetParameters());
return Expression.Lambda(
type,
Expression.Call(_delegate.Method, Expression.NewArrayInit(typeof(object),
typeargs.Select(arg => Expression.Convert(arg, typeof(object)))
)),
typeargs
).Compile();

Resources