I programming Windows Store App, and I have following problem.
I use this code to record the array of numbers to a file:
auto item = KnownFolders::PicturesLibrary;
task<StorageFile^> getFileTask(item->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting));
getFileTask.then([=](StorageFile^ storageFile)
{
return storageFile->OpenAsync(FileAccessMode::ReadWrite);
}).then([](IRandomAccessStream^ m_istream)mutable
{
unsigned char a[] = { 1, 2, 3 };
auto arr = ref new Array<unsigned char>(a, sizeof(a));
auto outs = m_istream->GetOutputStreamAt(0);
auto dw = ref new DataWriter(outs);
dw->WriteBytes(arr);
return dw->StoreAsync();
}).wait();
Code is successfully compiled, but it provide an error:
MyTest.exe has triggered a breakpoint.
And it point to _REPORT_PPLTASK_UNOBSERVED_EXCEPTION(); line, that be found in ppltasks.h.
If I use .then([](DataWriterStoreOperation^){}) instead .wait(), My application don't compile with this error:
error C2338: incorrect parameter type for the callable object in 'then';
consider _ExpectedParameterType or task<_ExpectedParameterType> (see below).
Why is that? I using VS2013. Please help me.
I found the solution of this problem!!!
Right code:
unsigned char a[] = { 1, 2, 3 };
auto arr = ref new Array<unsigned char>(a, sizeof(a));
auto m_istream = ref new InMemoryRandomAccessStream();
auto outs = m_istream->GetOutputStreamAt(0);
auto dw = ref new DataWriter(outs);
dw->WriteBytes(arr);
task<unsigned int>(dw->StoreAsync()).then([=](unsigned int)
{
return item->CreateFileAsync(filename, CreationCollisionOption::ReplaceExisting);
}).then([=](StorageFile^ storageFile)
{
return storageFile->OpenAsync(FileAccessMode::ReadWrite);
}).then([=](IRandomAccessStream^ new_stream)
{
return RandomAccessStream::CopyAsync(m_istream->GetInputStreamAt(0), new_stream->GetOutputStreamAt(0));
}).then([=](UINT64 copiedBytes)
{
return;
});
Related
I am trying to modify window's system menu using InsertMenuItem (instead of InsertMenu - the reason is that I want to insert submenus eventually). Language is C#.
Tried inserting a new item, tried getting existing item and reinserting it, it inserts, but the item string is shown in the menu only as the first character. Anyone have a clue about what I am missing?
// try creating one from scratch
MENUITEMINFO it = new MENUITEMINFO();
it.cbSize = (uint)Marshal.SizeOf(it);
it.fMask = 64;// MIIM_STRING
it.wID = 12345;
it.dwTypeData = "Now is the time";
it.fType = 0;
it.cch = 0;
InsertMenuItem(hSysMenu, 7, true, ref it);
//try copying one
GetMenuItemInfo(hSysMenu, (uint)0, true, ref it);
it.cch += 10;
it.dwTypeData = new string(' ', (int)(menuItemInfo.cch+10));
GetMenuItemInfo(hSysMenu, (uint)0, true, ref it);
it.wID = 123456;
var err = InsertMenuItem(hSysMenu, 1, true, ref it);
The result of the above code
Ok I finally figured it out. I will leave this here so maybe someone else later will find it when they are baffled by this.
The reason was that the InsertMenuItem p/invoke was defined with
[DllImport("user32.dll")] in the pinvoke.net site - see https://www.pinvoke.net/default.aspx/user32/insertmenu.html?diff=y
and it needs to be
[DllImport("user32.dll", CharSet = CharSet.Auto) ]
I changed the pinvoke.net page to reflect it.
I am working on an application that should compile and debug C# code on the fly.
A simplified version of the code is included below.
What should be changed in this code to run the generated method step by step and get the state of the variables x and y after each step?
If everything should be changed that is okay, I am happy with any constructive response.
EDIT: to clarify: what I want to do is have my code debug the code that is generated with reflection, not the debug function in Visual Studio.
string code =
#"
namespace MyNameSpace
{
public class MyClass
{
public static int MyMethod()
{
var x = 3;
var y = 4;
return x * y;
}
}
}";
string namespaceName = "MyNameSpace";
string className = "MyClass";
string methodName = "MyMethod";
string language = "csharp";
string classFullname = namespaceName + "." + className;
CodeDomProvider provider = CodeDomProvider.CreateProvider(language);
CompilerParameters parameters = new CompilerParameters();
CompilerResults results;
parameters.OutputAssembly = "Compiler";
parameters.CompilerOptions = "/t:library";
parameters.GenerateInMemory = true;
parameters.GenerateExecutable = false;
parameters.IncludeDebugInformation = true;
results = provider.CompileAssemblyFromSource(parameters, code);
if (results.Errors.Count != 0)
{
throw new Exception("Code compilation errors occurred.");
}
var instance = results.CompiledAssembly.CreateInstance(classFullname, false);
// TODO run the method step by step and get the state after each step
This configuration may help you:
parameters.GenerateInMemory = false; //default
parameters.TempFiles = new
TempFileCollection(Environment.GetEnvironmentVariable("TEMP"), true);
parameters.IncludeDebugInformation = true;
parameters.TempFiles.KeepFiles = true
To debug the generated code you will need the pdb files. To have those while debugging your application, just have to tell the compiler where to save the temporary files. For this you can just add the following line to your parameters:
parameters.TempFiles = new TempFileCollection(Environment.GetEnvironmentVariable("TEMP"), true);
You can then step into the Invokation of your targeted method. The Code could look like this:
var method = instance?.GetType().GetMethod(methodName);
method?.Invoke(instance, BindingFlags.InvokeMethod, null, null, CultureInfo.CurrentCulture);
If you want the Debugger to automatically stop, when entering your "MyMethod", you can modify your string likes this:
string code =
#"using System.Diagnostics;
namespace MyNameSpace
{
public class MyClass
{
public int MyMethod()
{
Debugger.Break();
var x = 3;
var y = 4;
return x * y;
}
}
}";
Elchido pointed out in the comments that maybe I should look for an interpreter. After a bit of searching I came across CSI: A Simple C# Interpreter.
https://www.codeproject.com/Articles/10212/CSI-A-Simple-C-Interpreter
After investigating, my conclusion is that it is possible to use either and interpreter or the Codedom compiler to create debugger-like functionality, but it takes a significant effort.
The solution that I am working on involves splitting the code into separate statements and put all variables in an array.
The 'MyMethod' function is split into parts:
public static object Line1()
{
return 3;
}
public static object Line2()
{
return 4;
}
public static object Line3(object x, object y)
{
return x*y;
}
After compiling the code using Codedom compiler, I can do the following:
Dictionary<string, object> vars = new Dictionary<string, object>();
List<MethodInfo> lines = new List<MethodInfo>();
lines.Add(type.GetMethod("Line1"));
lines.Add(type.GetMethod("Line2"));
lines.Add(type.GetMethod("Line3"));
vars["x"] = lines[0].Invoke(instance, new object[] { });
vars["y"] = lines[1].Invoke(instance, new object[] { });
vars["#return"] = lines[2].Invoke(instance, new object[] { vars["x"], vars["y"] });
Note that this is not a working solution yet, a lot of work still has to be done to convert the 'MyMethod code' into separate lines and extract the variables. I will post an update when I have more/better code.
Click just left side of your code it will mark red dot that is called break point.After that when your code execute at the point it will break at the point and you can debug step by step bt pressing F10 key.
Following my three previous posts, I can now pass a managed array of struct to my wrapped method. Here is an extract from the files:
// packer.i
typedef struct {
int width; // input
int height; // input
frame_t view; // output
frame_t dest; // output
} image_t;
CSHARP_ARRAYS(image_t, image_t)
%apply image_t INOUT[] { image_t *images }
int pack(image_t *images, int nb_images, parameters_t params);
Which generates a function with this signature:
// packer_cs.cs
public static int pack(image_t[] images, int nb_images, parameters_t arg2)
Which I call like this:
// Program.cs
var files = Directory.GetFiles("./images");
var images = new image_t[files.Length];
for (var f = 0; f < files.Length; f++)
{
using (var imgInfo = Image.FromFile(files[f]))
{
var imgStruct = new image_t()
{
width = imgInfo.Width,
height = imgInfo.Height,
dest = new frame_t(),
view = new frame_t()
};
images[f] = imgStruct;
}
}
var result = packer_cs.pack(images, images.Length, new parameters_t());
All is well and done, but when I run the pack() method, I have a protected memory access problem (System.AccessViolationException). Thankfully I have access to the source code of the C library, and Visual Studio automagically opens it for debugging and stepping through as soon as I enable unmanaged code debugging.
So, if I add a breakpoint at the start of the pack() function, and I use a watch to check images[x], I can see that the width and height values have nothing to do with what is provided (sometimes it's even 0 or negative). What's going on ? If I inspect my managed array on the C# side, the values are correctly stored and retrieved. Why doesn't C get the right values ? The other parameters (nb_images and params) don't have any problem.
Thank you !
Do the following:
Check that images[f].width and height have the values you expect
If yes, then check the SWIG-generated code to verify that those fields are properly copied.
If you can't spot any problem by looking at the code, you should break on packer_cs.pack and use the debugger to look at the wrapper code that copies the C# array to the C++ array, see what is wrong.
It is probably something in the typemaps that is incorrect. Once you know what that is, you can copy the typemaps code from SWIG source (the csharp_array.i file) to a new typemap in your .i and fix as required.
I have a class in managed C++ that has all its member variables initialized inside the constructor. The member of interest is an array. I am calling it from the .cs file of a C# project, having linked the two projects with the dll of the first one. However, the function says that one or more of the parameters are incorrect and therefore, cannot be used successfully.
The class declaration and the function declaration is as follows. Both are in the .h file.
Now, I would like to call the function in the .cs file as follows:
var Driver = new Driver();
long status = Driver.Config2("CAN0", 8, Driver.AttrIdList, Driver.AttrValueList);
Console.WriteLine(status);
If the function Config executes correctly, it should output a 0. However, I am getting a negative number and upon the lookup with the table provided by the vendor, it states that one or more of the parameters are not setup correctly. I have no idea how to get past this point since I'm a newbie to managed C++. All help would be greatly appreciated.
Thanks.
The code declaration is as follows:
public ref class Driver
{
public:
NCTYPE_STATUS Status;
NCTYPE_OBJH TxHandle;
MY_NCTYPE_CAN_FRAME Transmit;
array<NCTYPE_UINT32>^ AttrIdList;
array<NCTYPE_UINT32>^ AttrValueList;
array<char>^ Data;
NCTYPE_UINT32 Baudrate;
public:
Driver()
{
Baudrate = 1000000;
TxHandle = 0;
AttrIdList = gcnew array<NCTYPE_UINT32>(8);
AttrValueList = gcnew array<NCTYPE_UINT32>(8);
AttrIdList[0] = NC_ATTR_BAUD_RATE;
AttrValueList[0] = Baudrate;
AttrIdList[1] = NC_ATTR_START_ON_OPEN;
AttrValueList[1] = NC_TRUE;
AttrIdList[2] = NC_ATTR_READ_Q_LEN;
AttrValueList[2] = 0;
AttrIdList[3] = NC_ATTR_WRITE_Q_LEN;
AttrValueList[3] = 1;
AttrIdList[4] = NC_ATTR_CAN_COMP_STD;
AttrValueList[4] = 0;
AttrIdList[5] = NC_ATTR_CAN_MASK_STD;
AttrValueList[5] = NC_CAN_MASK_STD_DONTCARE;
AttrIdList[6] = NC_ATTR_CAN_COMP_XTD;
AttrValueList[6] = 0;
AttrIdList[7] = NC_ATTR_CAN_MASK_XTD;
AttrValueList[7] = NC_CAN_MASK_XTD_DONTCARE;
interior_ptr<NCTYPE_UINT32> pstart (&AttrIdList[0]);
interior_ptr<NCTYPE_UINT32> pend (&AttrIdList[7]);
Data = gcnew array<char>(8);
for (int i=0; i<8;i++)
Data[i]=i*2;
}
I also have another method right underneath the Config function that is declared as follows:
NCTYPE_STATUS Config2 (String^ objName, int numAttrs, array<unsigned long>^ AttrIdList, array<unsigned long>^ AttrValueList )
{
msclr::interop::marshal_context^ context = gcnew msclr::interop::marshal_context();
const char* name = context->marshal_as<const char*>(objName);
char* name_unconst = const_cast<char*>(name);
return ncConfig (name_unconst, 8, nullptr, nullptr);
delete context;
}
The program compiles and builds, this is a run-time error. I am guessing it has something to do with the two nullptr passed in the function Config2, but if I replace these with the parameters AttrIdList and AttrValueList, the compiler gives an error:
cannot convert parameter 3 from 'cli::array^' to 'NCTYPE_ATTRID_P'
BTW: NCTYPE_STATUS is unsigned long, while NCTYPE_ATTRID_P is unsigned long*.
cannot convert parameter 3 from 'cli::array^' to 'NCTYPE_ATTRID_P'
NCTYPE_ATTRID_P is unsigned long*
You can't pass a managed array to a pure native C++ function, you first need to 'convert' it to a fixed unsigned long* pointer.
Here's a way to do it:
unsigned long* ManagedArrayToFixedPtr(array<unsigned long>^input)
{
pin_ptr<unsigned long> pinned = &input[0];
unsigned long* bufferPtr = pinned;
unsigned long* output = new unsigned long[input->Length];
memcpy_s(output, input->Length, bufferPtr, input->Length);
return output;
}
Testing the function:
array<unsigned long>^ larray = gcnew array<unsigned long> {2,4,6,8,10,12,14,16};
unsigned long* lptr = ManagedArrayToFixedPtr(larray); //returns pointer to 2
Edit:
Rememer to #include "windows.h" to be able to use the memcpy_s function!
I'm embedding Mono in an MacOSX app written in Objective-c.
I'm accessing a C# lib (DDL), which only contains a bunch of static methods returning different types.
So far I can successfully get returned int, double and string, but I'm having trouble retrieving a returned array...
For exemple, here's how I retrieve an int:
MonoDomain *domain = mono_jit_init("TestDomain");
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* dll = [mainBundle pathForResource:#"TestLib86" ofType:#"dll"];
MonoAssembly* assembly = mono_domain_assembly_open(domain, [dll UTF8String]);
MonoImage* image = mono_assembly_get_image(assembly);
// Get INTEGER
// get a method handle to whatever you like
const char* descAsString = "MiniLib86.Show:GetInt()";
MonoMethodDesc* description = mono_method_desc_new(descAsString,TRUE);
MonoMethod* method = mono_method_desc_search_in_image(description, image);
// call it
void* args[0];
MonoObject *result = mono_runtime_invoke(method, NULL, args, NULL);
int int_result = *(int*)mono_object_unbox (result);
// See the result in log
NSLog(#"int result %i", int_result);
The method in C# that returns an List looks like this:
public static List<int> GetListInt()
{
return new System.Collections.Generic.List<int>{1,2,3,4,5};
}
Any help would be really appreciated !
Take a look at mono_runtime_invoke_array.