I have seen a great answer here which has helped me to a great extent (Proper way to create unique_ptr that holds an allocated array) but I still have an issue.
Code:
void CSelectedBroHighlight::BuildSelectedArray()
{
CString strText;
// empty current array
m_aryStrSelectedBro.RemoveAll();
// get selected count
const auto iSize = m_lbBrothers.GetSelCount();
if(iSize > 0)
{
//auto pIndex = std::make_unique<int[]>(iSize);
auto pIndex = new int[iSize];
m_lbBrothers.GetSelItems(iSize, pIndex);
for(auto i = 0; i < iSize; i++)
{
m_lbBrothers.GetText(pIndex[i], strText);
m_aryStrSelectedBro.Add(strText);
}
delete[] pIndex;
}
}
If I turn pIndex into a smart pointer:
auto pIndex = std::make_unique<int[]>(iSize);
So that I don't need the delete[] pIndex; call. Then I can't pass pIndex to GetSelItems. I can pass pIndex.release() here but then we have a problem for deleting again.
I have looked at this discussion (Issue passing std::unique_ptr's) but we don't want to pass ownership.
If I simplify this and declar my variable: auto pIndex = std::make_unique<int[]>(iSize).release(); then I can pass it, but now have the issue of calling delete[] pIndex;.
Whats correct?
If you need access to the pointer to an object managed by a std::unique_ptr without transferring ownership, you can call its get() method. This is useful for interop with a C interface such as here (GetSelItems() is really just wrapping a call to SendMessage with the LB_GETSELITEMS message).
That'd work, though in this case I'd probably use a std::vector<int> instead. It provides the same properties as a std::unique_ptr with respect to automatic cleanup, but also has other features that come in handy (specifically range adapters). It also feels more natural to use a container here, but that's a matter of personal preference.
The following implements the proposed changes:
void CSelectedBroHighlight::BuildSelectedArray() {
// empty current array
m_aryStrSelectedBro.RemoveAll();
// get selected count
auto const sel_item_count{ m_lbBrothers.GetSelCount() };
if(sel_item_count > 0) {
// get selected indices
std::vector<int> sel_items(sel_item_count);
m_lbBrothers.GetSelItems(sel_items.size(), sel_items.data());
// iterate over all selected item indices
for(auto const index : sel_items) {
CString strText;
m_lbBrothers.GetText(index, strText);
m_aryStrSelectedBro.Add(strText);
}
}
}
This provides the same automatic cleanup as an implementation based on std::unique_ptr, but also enables use of a range-based for loop further down.
Related
For example, consider the following C# code:
interface IBase { void f(int); }
interface IDerived : IBase { /* inherits f from IBase */ }
...
void SomeFunction()
{
IDerived o = ...;
o.f(5);
}
I know how to get a MethodDefinition object corresponding to SomeFunction.
I can then loop through MethodDefinition.Instructions:
var methodDef = GetMethodDefinitionOfSomeFunction();
foreach (var instruction in methodDef.Body.Instructions)
{
switch (instruction.Operand)
{
case MethodReference mr:
...
break;
}
yield return memberRef;
}
And this way I can find out that the method SomeFunction calls the function IBase.f
Now I would like to know the declared type of the object on which the function f is called, i.e. the declared type of o.
Inspecting mr.DeclaringType does not help, because it returns IBase.
This is what I have so far:
TypeReference typeRef = null;
if (instruction.OpCode == OpCodes.Callvirt)
{
// Identify the type of the object on which the call is being made.
var objInstruction = instruction;
if (instruction.Previous.OpCode == OpCodes.Tail)
{
objInstruction = instruction.Previous;
}
for (int i = mr.Parameters.Count; i >= 0; --i)
{
objInstruction = objInstruction.Previous;
}
if (objInstruction.OpCode == OpCodes.Ldloc_0 ||
objInstruction.OpCode == OpCodes.Ldloc_1 ||
objInstruction.OpCode == OpCodes.Ldloc_2 ||
objInstruction.OpCode == OpCodes.Ldloc_3)
{
var localIndex = objInstruction.OpCode.Op2 - OpCodes.Ldloc_0.Op2;
typeRef = locals[localIndex].VariableType;
}
else
{
switch (objInstruction.Operand)
{
case FieldDefinition fd:
typeRef = fd.DeclaringType;
break;
case VariableDefinition vd:
typeRef = vd.VariableType;
break;
}
}
}
where locals is methodDef.Body.Variables
But this is, of course, not enough, because the arguments to a function can be calls to other functions, like in f(g("hello")). It looks like the case above where I inspect previous instructions must repeat the actions of the virtual machine when it actually executes the code. I do not execute it, of course, but I need to recognize function calls and replace them and their arguments with their respective returns (even if placeholders). It looks like a major pain.
Is there a simpler way? Maybe there is something built-in already?
I am not aware of an easy way to achieve this.
The "easiest" way I can think of is to walk the stack and find where the reference used as the target of the call is pushed.
Basically, starting from the call instruction go back one instruction at a time taking into account how each one affects the stack; this way you can find the exact instruction that pushes the reference used as the target of the call (a long time ago I wrote something like that; you can use the code at https://github.com/lytico/db4o/blob/master/db4o.net/Db4oTool/Db4oTool/Core/StackAnalyzer.cs as inspiration).
You'll need also to consider scenarios in which the pushed reference is produced through a method/property; for example, SomeFunction().f(5). In this case you may need to evaluate that method to find out the actual type returned.
Keep in mind that you'll need to handle a lot of different cases; for example, imagine the code bellow:
class Utils
{
public static T Instantiate<T>() where T : new() => new T();
}
class SomeType
{
public void F(int i) {}
}
class Usage
{
static void Main()
{
var o = Utils.Instantiate<SomeType>();
o.F(1);
}
}
while walking the stack you'll find that o is the target of the method call; then you'll evaluate Instantiate<T>() method and will find that it returns new T() and knowing that T is SomeType in this case, that is the type you're looking for.
So the answer of Vagaus helped me come up with a working implementation.
I published it on github - https://github.com/MarkKharitonov/MonoCecilExtensions
Included many unit tests, but I am sure I missed some cases.
I've got a GUI with a TabControl. Each new TabPage is created via a new Thread. I want to call this->tabControl->TabCount, but the tabControl is owned by a thread other than the one I'm calling from. Therefore, I need to Invoke a delegate. However, all the examples I find online show printing to std::cout from each of the delegate methods. I need a return value, in this case an int.
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del); // can't just "return this->Invoke(del)"
return temp; // Invoke() returns a System::Object^
}
else
{
return this->tabControl->TabCount;
}
}
void CreateNewTab()
{
// do stuff
this->tabControl->TabPages->Insert(InvokeTabCount() - 1, myNewTab); // insert a tab
this->tabControl->SelectTab(InvokeTabCount() - 2); // OutOfBounds and tabPageNew
}
System::Void MethodToAddNewTabPage() //actually a click event but whatever
{
System::Threading::Thread^ newThread =
gcnew System::Threading::Thread(
gcnew System::Threading::ThreadStart(this, &MyTabControl::CreateNewTab));
newThread->Start();
}
Currently, my InvokeTabCount() method is returning -1 when I simply this->Invoke(del) without returning it. And I am unable to return it because my method expects to return an int instead of a System::Object^ which is what Invoke() returns. However, when debugging I find that auto temp contains the value 2 which is correct. And temp->ToString() contains the value "2" which would also be correct.
How do I return this->Invoke(del)?
Do I need to set the value of a global variable from within my InvokeTabCount() method? I suppose I could find a way to translate from System::String^ to std::string to utilize std::stoi(), but that seems like an odd workaround.
Current solution:
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del);
return int::Parse(temp->ToString());
}
else
{
return this->tabControl->TabCount;
}
}
The result is an integer, boxed and contained in an Object^ reference. You should be able to simply cast it to int.
If you want to be extra safe, do a null check and verify that temp->GetType() returns int::typeid, but that's probably overkill since you're creating the delegate (still in the typed form) right there.
So far I've only written console applications. My first application using MFC (in Visual Studio 2010) is basically a form with two multiline boxes (using String[] arrays noted with String^) and a button to activate text processing. It should search the String^ for a [, look for the ] behind it and delete all characters between them (including the []). With 'normal' C++ strings, this isn't difficult. String^ however is more like an object and MSDN tells me to make use of the Remove method. So, I tried to implement it.
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: Add the constructor code here
//
}
String^ DestroyCoords(String^ phrase)
{
int CoordsStart = 0;
int CoordsEnd = 0;
int CharCount = 0;
for each (Char ch in phrase)
{
if (ch == '[')
CoordsStart = CharCount;
if (ch == ']')
{
CoordsEnd = CharCount;
//CoordsEnd = phrase->IndexOf(ch);
phrase->Remove( CoordsStart , CoordsEnd-CoordsStart );
}
CharCount++;
}
return phrase;
}
The button using the method:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
TempString = String::Copy(BoxInput->Text);
DestroyCoords(TempString);
BoxOutput->Text = TempString;
The function seems to hit the correct places at the correct time, but the phrase->Remove() method is doing absolutely nothing..
I'm no OO hero (as said, I normally only build console applications), so it's probably a rookie mistake. What am I doing wrong?
In C++/CLI, System::String is immutable, so Remove creates a new String^. This means you'll need to assign the results:
phrase = phrase->Remove( CoordsStart , CoordsEnd-CoordsStart );
The same is true in your usage:
TempString = DestroyCoords(TempString);
BoxOutput->Text = TempString;
Note that this will still not work, as you'd need to iterate through your string in reverse (as the index will be wrong after the first removal).
No MFC here, that's the C++/CLI that Microsoft uses for writing .NET programs in C++.
The .NET System::String class is immutable, so any operations you expect to modify the string actually return a new string with the adjustment made.
A further problem is that you're trying to modify a container (the string) while iterating through it. Instead of using Remove, have a StringBuilder variable and copy across the parts of the string you want to keep. This means only a single copy and will be far faster than repeated calls to Remove each of which makes a copy. And it won't interfere with iteration.
Here's the right approach:
int BracketDepth = 0;
StringBuilder sb(phrase->Length); // using stack semantics
// preallocated to size of input string
for each (Char ch in phrase)
{
if (ch == '[') { // now we're handling nested brackets
++BracketDepth;
}
else if (ch == ']') { // and complaining if there are too many closing brackets
if (!BracketDepth--) throw gcnew Exception();
}
else if (!BracketDepth) { // keep what's not brackets or inside brackets
sb.Append(ch);
}
}
if (BracketDepth) throw gcnew Exception(); // not enough closing brackets
return sb.ToString();
Background worker, passing variables are not working, in my example I explain everything, I put only the functions that were important, I have the other functions from the BackgroundWorker.
int TheFunction(unordered_map<std::string,std::string> options, BackgroundWorker^ worker, DoWorkEventArgs ^ e){
if(options["option1"].compare("options") == 0){
//...
}
return 0;
}
void backgroundWorker2_DoWork(Object^ sender, DoWorkEventArgs^ e ){
BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
//e->Result = TheFunction( safe_cast<Int32>(e->Argument), worker, e ); //That's how I do to send an integer value and works just fine, but I don't know how to send non-numeric values with safe_cast or something that works, in the function it looks like this: TheFunction(int index, ...) it works fine, I want to know with unordered_map or with strings also would work, I want more than one argument if you can do with std::string
e->Result = TheFunction(safe_cast<unordered_map<std::string,std::string>>(e->Argument)); //I tried this, and it didn't work
}
void CallBackgroundWorker(){
this->backgroundWorker2 = gcnew System::ComponentModel::BackgroundWorker;
this->backgroundWorker2->WorkerReportsProgress = true;
this->backgroundWorker2->WorkerSupportsCancellation = true;
this->backgroundWorker2->DoWork += gcnew DoWorkEventHandler( this, &GUISystem::backgroundWorker2_DoWork );
this->backgroundWorker2->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &GUISystem::backgroundWorker2_RunWorkerCompleted );
this->backgroundWorker2->ProgressChanged += gcnew ProgressChangedEventHandler( this, &GUISystem::backgroundWorker2_ProgressChanged );
unordered_map<std::string,std::string>* options = unordered_map<std::string,std::string>();
options["option1"] = "valor1";
options["option2"] = "valor2";
this->backgroundWorker2->RunWorkerAsync(options);
}
So how do I do to send the unordered_map or a std::string (more than 1 arguments) ?
thanks in advance. that would help a lot.
This line:
unordered_map<std::string,std::string>* options = unordered_map<std::string,std::string>();
isn't legal even in standard C++. A pointer needs to store an address, not an object. So probably you meant to say new to use dynamic allocation (after all, the object needs to survive until the callback runs on the other thread).
At that point, you can wrap the pointer inside System::IntPtr, and in the callback, cast the result of ToPointer().
Consider the following struct:
public struct vip
{
string email;
string name;
int category;
public vip(string email, int category, string name = "")
{
this.email = email;
this.name = name;
this.category = category;
}
}
Is there a performance difference between the following two calls?
var e = new vip(email: "foo", name: "bar", category: 32);
var e = new vip("foo", 32, "bar");
Is there a difference if there are no optional parameters defined?
I believe none. It's only a language/compiler feature, call it syntactic sugar if you like. The generated CLR code should be the same.
There's a compile-time cost, but not a runtime one...and the compile time is very, very minute.
Like extension methods or auto-implemented properties, this is just magic the compiler does, but in reality generates the same IL we're all familiar with and have been using for years.
Think about it this way, if you're using all the parameters, the compiler would call the method using all of them, if not, it would generate something like this behind the scenes:
var e = new vip(email: "foo", category: 32); //calling
//generated, this is what it's actually saving you from writing
public vip(string email, int category) : this(email, category, "bar") { }
No it is a compile-time feature only. If you inspect the generated IL you'll see no sign of the named parameters. Likewise, optional parameters is also a compile-time feature.
One thing to keep in mind regarding named parameters is that the names are now part of the signature for calling a method (if used obviously) at compile time. I.e. if names change the calling code must be changed as well if you recompile. A deployed assembly, on the other hand, will not be affected until recompiled, as the names are not present in the IL.
There shouldn't be any. Basically, named parameters and optional parameters are syntactic sugar; the compiler writes the actual values or the default values directly into the call site.
EDIT: Note that because they are a compiler feature, this means that changes to the parameters only get updated if you recompile the "clients". So if you change the default value of an optional parameter, for example, you will need to recompile all "clients", or else they will use the old default value.
Actually, there is cost at x64 CLR
Look at here http://www.dotnetperls.com/named-parameters
I am able to reproduce the result: named call takes 4.43 ns, and normal call takes 3.48 ns
(program runs in x64)
However, in x86, both take around 0.32 ns
The code is attached below, compile and run it yourself to see the difference.
Note that in VS2012 the default targat is AnyCPU x86 prefered, you have to switch to x64 to see the difference.
using System;
using System.Diagnostics;
class Program
{
const int _max = 100000000;
static void Main()
{
Method1();
Method2();
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method1();
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method2();
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) /
_max).ToString("0.00 ns"));
Console.Read();
}
static void Method1()
{
Method3(flag: true, size: 1, name: "Perl");
}
static void Method2()
{
Method3(1, "Perl", true);
}
static void Method3(int size, string name, bool flag)
{
if (!flag && size != -1 && name != null)
{
throw new Exception();
}
}
}