Parallel.For(<your starting value >,<End criteria for loop>, delegate(int < your variable Name>)
{
// Your own code
});
Here above I am showing some sample code in C#. I want similar functionality in C++/CLI but I don't know how to use this expression: "delegate(int < your variable Name>)".
If you are using c++cli, then you should be able to use the same Parallel.For that you use in C# since System.Threading.Tasks.Parallel is a regular .Net Framework class
Example (untested, not even compiled):
ref class SomeClass
{
public:
static void Func(int index)
{
Console::WriteLine("Test {0}", index);
}
};
delegate void MyCallback(int index);
int main( )
{
MyCallback^ callback = gcnew MyCallback(SomeClass::Func);
Parallel.For(0, 9, callback);
}
Relevant: How to: Define and Use Delegates in C++/CLI
Related
I have project which I am compiling with /clr. I have a class like below..
ref class A
{
public:
void CheckValue(void * test);
typedef ref struct val
{
std::string *x;
}val_t;
};
in my implementation I ahve to use something like below..
void A::CheckValue(void *test)
{
a::val_t^ allVal = (a::val_t^)test;
}
in my main I have used like..
int main()
{
A^ obj = gcnew A();
a::val_t valObj = new std::string("Test");
obj->CheckValue((void*)valObj);
}
I am getting type cast error and two places -
obj->CheckValue((void*)valObj);
and at
obj->CheckValue((void*)valObj);
error C2440: 'type cast' : cannot convert from 'void*' to 'A::val_t ^'
This snippet is just to show behavior at my end and I ahve to use it this way only. Earlier I was running it using non /clr so it compiled fine.
Now question I have how can I make this type casting work in C++/CLI type project?
Replace void * with Object^. You can also write a generic version of CheckValue but then there is not much point of having a weak-typed parameter when you have the type in the generic parameter.
A reference handle represents an object on the managed heap. Unlike a native pointer, CLR could move the object around during a function call, so the behavior of a pointer and a reference handle is different, and a type cast would fail. You can also pin the object being referenced using pin_ptr if you really need a void* so CLR would not be moving the object during the function call.
Here is how I would get around the limitation you are seeing, just remove the struct from the managed object, since it contains native pointer types.
struct val_t
{
char* x;
};
ref class A
{
public:
void CheckValue(void* test);
};
void A::CheckValue(void* test)
{
val_t* allVal = (val_t*)test;
}
int main()
{
A^ obj = gcnew A();
val_t valObj;
valObj.x = "Test";
obj->CheckValue((void*)&valObj);
}
Now, if you absolutely need the struct to be managed, here is how to do it:
ref class A
{
public:
void CheckValue(void * test);
value struct val_t
{
char* x;
};
};
void A::CheckValue(void *test)
{
a::val_t* allVal = (a::val_t*)test;
}
int main()
{
A^ obj = gcnew A();
a::val_t valObj;
valObj.x = "Test";
pin_ptr<a::val_t> valPin = &valObj;
obj->CheckValue((void*)valPin);
}
I've been given a third party C/C++ library (.dll, .lib, .exp and .h) that I need to use in our C# app.
ThirdPartyLibrary.h contains...
class AClass {
public:
typedef enum {
green = 7,
blue = 16
} Color;
virtual int GetData()=0;
virtual int DoWork(Color, char *)=0;
};
void * Func1(int, AClass **aClass);
In my C++/CLI code I have done this...
#include "ThirdPartyLibrary.h"
using namespace System;
using namespace System::Runtime::InteropServices;
namespace Wrapper {
public ref class MyBridgeClass
{
private:
AClass* pAClass;
public:
// C# code will call this method
void AMethod (int x)
{
int y = x+10;
Func1 (y, &(this->pAClass)); // <-- error!
}
}
}
I get a build error that reads...
cannot convert parameter 2 from 'cli::interior_ptr<Type>' to 'AClass **'
with
[
Type=AClass *
]
Cannot convert a managed type to an unmanaged type
Any ideas? Maybe I need #pragma manage/unmanged tags in my C++/CLI?
The reason you're getting that error is because of how managed memory works.
In your managed class, you've got a pointer defined. The address of that pointer is part of the managed object, and can change when the garbage collector runs. That's why you can't just pass &pAClass to the method, the GC can change what that address actually is.
There's a couple things you can do to fix this:
You could create an unmanaged helper class to hold the AClass* member. I'd do this if that pointer needs to stay valid beyond the invocation of this method, or if you have a lot of unmanaged pointers to hold.
struct UnmanagedHolder
{
AClass* pAClass;
};
public ref class MyBridgeClass
{
private:
// must create in constructor, delete in destructor and finalizer.
UnmanagedHolder* unmanaged;
public:
// C# code will call this method
void AMethod (int x)
{
int y = x+10;
Func1 (y, &(this->unmanaged->pAClass));
}
};
If you only need the pointer to be valid within AMethod, and the pointer doesn't need to remain valid after the call to Func1, then you can use a pin_ptr.
void AMethod (int x)
{
int y = x+10;
pin_ptr<AClass*> pin = &(this->pAClass);
Func1 (y, pin);
}
I’ve a question about creating a C++ CLI Wrapper for a native C++ class to be used in C#.
Here is an example code:
#include "stdafx.h"
#pragma once
using namespace System;
namespace Wrapper {
class NativeClass
{
public:
NativeClass() {}
int Add(int a, int b)
{
return a+b;
}
};
public ref class Wrapper
{
public:
Wrapper() {pNative = new NativeClass();}
int Add(int a, int b)
{
return(pNative->Add(a,b));
}
~Wrapper()
{
delete pNative;
pNative = 0;
}
!Wrapper()
{
this->~Wrapper();
}
//My problem is here.
NativeClass* GetNative()
{
return pNative;
}
private:
NativeClass* pNative;
};
}
This code works fine. I need to retrieve the pointer that refers the native class to use it in the other wrapper classes. However, I don’t want the function “GetNative” to be visible in C# when I’m using this wrapper class. How can I hide it?
If the other wrapper classes are in the same assembly, make the access internal instead of public. – Roger Rowland Apr 25 '13 at 9:47
.
if they are not in the same assembly? ...
Look into friend assemblies – Sebastian Cabot Feb 1 at 15:43
I have this code for the C# in Visual Studio 2012.
public Task SwitchLaserAsync(bool on)
{
return Task.Run(new Action(() => SwitchLaser(on)));
}
This will execute SwitchLaser method (public nonstatic member of a class MyClass) as a task with argument bool on.
I would like to do something similar in managed C++/CLI. But I am not able to find out any way how to run a task, which will execute a member method taking one parameter.
Current solution is like this:
Task^ MyClass::SwitchLaserAsync( bool on )
{
laserOn = on; //member bool
return Task::Run(gcnew Action(this, &MyClass::SwitchLaserHelper));
}
Implementation of SwitchLaserHelper function:
void MyClass::SwitchLaserHelper()
{
SwitchLaser(laserOn);
}
There must be some solution like in C# and not to create helper functions and members (this is not threadsafe).
There isn't yet any way to do this.
In C# you have a closure. When your C++/CLI compiler was written, the standardized syntax for closures in C++ was still being discussed. Thankfully, Microsoft chose to wait and use the standard lambda syntax instead of introducing yet another unique syntax. Unfortunately, it means the feature isn't yet available. When it is, it will look something like:
gcnew Action([this, on](){ SwitchLaser(on) });
The current threadsafe solution is to do what the C# compiler does -- put the helper function and data members not into the current class, but into a nested subtype. Of course you'll need to save the this pointer in addition to your local variable.
ref class MyClass::SwitchLaserHelper
{
bool laserOn;
MyClass^ owner;
public:
SwitchLaserHelper(MyClass^ realThis, bool on) : owner(realThis), laserOn(on) {}
void DoIt() { owner->SwitchLaser(laserOn); }
};
Task^ MyClass::SwitchLaserAsync( bool on )
{
return Task::Run(gcnew Action(gcnew SwitchLaserHelper(this, on), &MyClass::SwitchLaserHelper::DoIt));
}
The C++ lamdba syntax will simply create that helper class for you (currently it works for native lambdas, but not yet for managed ones).
Here's generic code I wrote this afternoon which might help (although it's not an exact match for this question). Maybe this will help the next person who stumbles onto this question.
generic<typename T, typename TResult>
ref class Bind1
{
initonly T arg;
Func<T, TResult>^ const f;
TResult _() { return f(arg); }
public:
initonly Func<TResult>^ binder;
Bind1(Func<T, TResult>^ f, T arg) : f(f), arg(arg) {
binder = gcnew Func<TResult>(this, &Bind1::_);
}
};
ref class Binder abstract sealed // static
{
public:
generic<typename T, typename TResult>
static Func<TResult>^ Create(Func<T, TResult>^ f, T arg) {
return (gcnew Bind1<T, TResult>(f, arg))->binder;
}
};
Usage is
const auto f = gcnew Func<T, TResult>(this, &MyClass::MyMethod);
return Task::Run(Binder::Create(f, arg));
Here's the working answer.. Have tested it.. Passing an argument (int) to the action sampleFunction.
#include "stdafx.h"
#include "CLRSamples.h"
using namespace System;
using namespace System::Threading;
using namespace System::Threading::Tasks;
using namespace System::Collections;
using namespace System::Collections::Generic;
void CLRSamples::sampleFunction(Object^ number)
{
Console::WriteLine(number->ToString());
Thread::Sleep((int)number * 100);
}
void CLRSamples::testTasks()
{
List<Task^>^ tasks = gcnew List<Task^>();
for (int i = 0; i < 10; i++)
{
tasks->Add(Task::Factory->StartNew((Action<Object^>^)(gcnew Action<Object^>(this, &CLRSamples::sampleFunction)), i));
}
Task::WaitAll(tasks->ToArray());
Console::WriteLine("Completed...");
}
int main(array<System::String ^> ^args)
{
CLRSamples^ samples = gcnew CLRSamples();
samples->testTasks();
Console::Read();
return 0;
}
I had a similar problem when I wanted to provide a parameter to a task executing a method which does not return a value (retuns void). Because of that Func<T, TResult> was not an option I could use. For more information, please check the page Using void return types with new Func.
So I ended up with a solution where I created a helper class
template <typename T>
ref class ActionArguments
{
public:
ActionArguments(Action<T>^ func, T args) : m_func(func), m_args(args) {};
void operator()() { m_func(m_args); };
private:
Action<T>^ m_func;
T m_args;
};
which is using Action<T> delegate to encapsulate a method that has a single parameter and does not return a value.
I would then use this helper class in a following way
ref class DisplayActivationController
{
public:
DisplayActivationController();
void StatusChanged(EventArgs^ args) { };
}
Action<EventArgs^>^ action =
gcnew Action<EventArgs^>(this, &DisplayActivationController::StatusChanged);
ActionArguments<EventArgs^>^ action_args =
gcnew ActionArguments<EventArgs^>(action, args);
Threading::Tasks::Task::Factory->
StartNew(gcnew Action(action_args, &ActionArguments<EventArgs^>::operator()));
Approach using the helper class is probably not the most elegant solution, but is the best one I could find to be used in C++/CLI which does not support lambda expressions.
If you are using c++/ CLR, then make a C# dll and add reference to it
namespace TaskClrHelper
{
public static class TaskHelper
{
public static Task<TResult> StartNew<T1, TResult>(
Func<T1, TResult> func,
T1 arg)
=> Task.Factory.StartNew(() => func(arg));
public static Task<TResult> StartNew<T1, T2, TResult>(
Func<T1, T2, TResult> func,
T1 arg1, T2 arg2)
=> Task.Factory.StartNew(() => func(arg1, arg2));
}
}
bool Device::Stop(int timeout)
{
_ResetEvent_Running->Set();
return _ResetEvent_Disconnect->WaitOne(timeout);
}
Task<bool>^ Device::StopAsync(int timeout)
{
auto func = gcnew Func<int, bool>(this, &Device::Stop);
return TaskClrHelper::TaskHelper::StartNew<int,bool>(func,timeout);
}
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;
}