I'm try to make a sort delegate in C++/CLI, but, when I try to compile I recive this erro:
>app.cpp(256): error C3374: can't take address of 'Program::AnonymousMethod1' unless creating delegate instance
>app.cpp(256): error C2664: 'void System::Collections::Generic::List<T>::Sort(System::Comparison<T> ^)' : cannot convert parameter 1 from 'System::Object ^(__clrcall *)(Program::teste1,Program::teste1)' to 'System::Comparison<T> ^'
> with
> [
> T=Program::teste1 ^
> ]
> No user-defined-conversion operator available, or
> There is no context in which this conversion is possible
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
here is the code sample of the error:
using namespace System;
using namespace System::Collections::Generic;
private ref class Program
{
private:
enum class tokens
{
teste,
lala,
blabla,
};
ref struct teste1
{
int linha;
tokens tk;
};
private:
static Object ^AnonymousMethod1(teste1 p1, teste1 p2)
{
return p1.tk.CompareTo(p2.tk);
}
public:
Program()
{
bool jump = false;
List<teste1^>^ lstTest = gcnew List<teste1^>();
Random ^rnd = gcnew Random();
for (int i = 0; i < 20; i++)
{
teste1 ^tst = gcnew teste1();
switch (rnd->Next(1,4))
{
case 1:
tst->tk = tokens::teste;
break;
case 2:
tst->tk = tokens::lala;
break;
case 3:
tst->tk = tokens::blabla;
break;
}
lstTest->Add(tst);
}
for each (teste1^ content in lstTest)
{
Console::WriteLine(content->tk.ToString());
}
lstTest->Sort(AnonymousMethod1);
Console::WriteLine("==============================================================");
for each (teste1^ content in lstTest)
{
Console::WriteLine(content->tk.ToString());
}
}
};
int main(array<String^> ^args)
{
Program^ prg = gcnew Program();
return 0;
}
I just whant to sort the list with the token 'lala' first, how I can make this, and, How I can solve this ???
Your List is of type List<test1^> (notice the ^ hat). So the Comparison<T> delegate you want is Comparison<teste1^>. Thus you'll want to change your AnonymousMethod1 as follows:
static int AnonymousMethod1(teste1 ^ p1, teste1 ^ p2)
{
return p1->tk.CompareTo(p2->tk);
}
And in C++/CLI you need to explicitly create your delegate:
Comparison<teste1 ^> ^ comparisonDelegate = gcnew Comparison<teste1 ^>(&AnonymousMethod1);
lstTest->Sort(comparisonDelegate);
Related
Hello i am bigginer in programing and i have specific problem.
I have been learning a new ways to write a code in small Arduino project.
that project have multiple objects like distance measuring Senzor, led diods , temperature senzor, etc. And all this objects have its own menu where you can, for example, start a calibration or just get values.
What i need is singleton class that has a function enter_esc() that need a int (*funct)() parameter basically function pointer.
That enter_esc(int (*funct)()) function just looping function until you press escape pin which is defined.
function Calibration() have inside some private: object data types like value or cali_value.
so i tried to insert function Calibration() right into enter_esc(Calibration) but it won't compile becouse i didnt pass that vlaues by reference or copy.
but what i found is lambda.
i made a lamda similar to a Calibration() function and i passed values by reference &{//domething;}
but i had to use enter_esc(std::function<int()>& funct) whitch is only int C++ standard library and not in Arduino C/C++ so my qestion is:
[is there some way how to pass values by reference by using lambda to a singleton class in Arduino ?]
(i konw it can be done differently but like i said i want to learn some new ways to program, also if you have some different way to make it i will by very happy to see it)
10Q for your time :)
//Class.h
#pragma once
class events {
private:
static events e_instance;
int p_menu, p_enter, p_esc, p_up, p_down;
int menuValue;
events();
public:
events(const events&) = delete;
static events& Get();
int ArrowUpDown(int maxVal);
int ArrowUpDown(int p_up, int p_down, int maxVal);
int enter_esc(const std::function<int()>& funct);
};
events events::e_instance;
class deviceBase : public Printables
{
public:
const char* a_pin;
int d_pin;
String type;
String deviceName;
bool inUse;
int actualCount;
public:
String getType() override;
int getActualCount() override;
String getName() override;
String getInUse() override;
};
class senzor : public deviceBase
{
private:
int Value;
int triggValue;
public:
int p_triggValue = 10;
static int allSenzors;
friend events;
senzor();
~senzor();
public:
int getValue();
int Calibration();
void changeTriggVal(int x);
void Reset();
void nullCalibration();
void Menu(int x);
void setName(String deviceName);
void setInUse(bool x);
int getPin();
};
int senzor::allSenzors = 0;
if you have some good advice to my code writing i will be also very glad
//Class.cpp
#include <iostream>
#include <string>
#include <functional>
#define LOG(x) std::cout << x << std::endl;
#define PINMENU 12
#define PINENTER 8
#define PINESC 9
#define PINUP 11
#define PINDOWN 13
using String = std::string;
struct Printables
{
virtual String getType() = 0;
virtual int getActualCount() = 0; ;
virtual String getName() = 0;
virtual String getInUse() = 0;
};
#include "Class.h"
events& events::Get() {
return e_instance;
}
int events::ArrowUpDown(int maxVal) {
if (maxVal) {
menuValue = menuValue < maxVal ? menuValue++ : menuValue;
}
if (maxVal) {
menuValue = menuValue > 0 ? menuValue-- : menuValue;
}
return menuValue;
}
int events::enter_esc(const std::function<int()>&funct) {
if (1) {
while (!p_esc) {
auto f = funct;
}
}
return 1;
}
int events::ArrowUpDown(int p_up, int p_down, int maxVal) { return 666; }
events::events() {};
String deviceBase::getType() { return type; }
int deviceBase::getActualCount() { return actualCount; }
String deviceBase::getName() { return deviceName; }
String deviceBase::getInUse() {
String Status;
Status = inUse == 1 ? "Active" : "Deactive";
return Status;
}
senzor::senzor() : Value(0), triggValue(1) {
a_pin = "xx";
type = "[SENZOR]";
deviceName = "[UNKNOWN]";
inUse = 0;
allSenzors++;
actualCount = allSenzors;
a_pin = 0;
}
senzor::~senzor() {
allSenzors = 0;
}
int senzor::getValue() {
Value = 4;
return Value;
}
int senzor::Calibration() {
triggValue = triggValue < getValue() ? getValue() : triggValue;
p_triggValue = triggValue;
return p_triggValue;
}
void senzor::changeTriggVal(int x) {
p_triggValue = x;
}
void senzor::Reset() {
p_triggValue = triggValue;
}
void senzor::nullCalibration() {
triggValue = 1;
}
void senzor::setName(String deviceName) {
this->deviceName = deviceName;
}
void senzor::setInUse(bool x) {
inUse = x;
}
int senzor::getPin() {
return 4;
}
int printsss() {
return 1;
}
////////////////////////////////this what i was writing about//////////////////////////////
void senzor::Menu(int x) {
events::Get().enter_esc([&]() { triggValue = triggValue < getValue() ? getValue() : triggValue;
p_triggValue = triggValue;
return p_triggValue; });
}
but if i use lambda in arduino with enter_esc(int (*funct)()) i get this kind of error
no matching function for call to 'events::enter_esc(senzor::Menu(int)::<lambda()>)'
Example Program 1
Step 1: Create a class 'Number'
Step 2: Declare Non-Static field/variable.
Step 3: Create another class ‘EncapTest’.
Step 4: Create an object of class Number.
Step 5: Print the values in the variable.
#include<iostream>
using namespace std;
class Number
{
private:
int var1;
public:
Number(){var1=0;}
Number(int var1)
{ this->var1=var1; }
void setValue(int var1=0)
{
this->var1 = var1;
}
int getValue()
{ return var1; }
};
class EncapTest
{
private:
Number obj;
public:
EncapTest () {obj.setValue();}
EncapTest (int var1)
{ obj.setValue(var1); }
void showOutput()
{
cout << "The value stored in variable is: " << obj.getValue()<<endl;
}
};
int main ()
{
EncapTest object (3);
object.showOutput();
return 0;
}
I' trying to make an identical function to "ioctl" in c++ style using boost library.
Here is my "c" style code:
int sockfd;
char * id;
struct iwreq wreq;
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
exit(1);
}
printf("Socket opened successfully \n");
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
if (ioctl(sockfd, SIOCGIWESSID, &wreq)) {
fprintf(stderr, "Get ESSID ioctl failed \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description : %s\n",strerror(errno));
exit(2);
}
printf("IOCTL Successfull\n");
printf("ESSID is %s\n", wreq.u.essid.pointer);
I found some relevant example, but I'm not clear how to use it correctly. example
Main function:
boost::asio::ip::udp::socket socket(io_service);
struct iwreq wreq
memset(&wreq, 0, sizeof(struct iwreq));
sprintf(wreq.ifr_name, IW_INTERFACE);
id = malloc(IW_ESSID_MAX_SIZE+1);
wreq.u.essid.pointer = id;
boost::asio::detail::io_control::myCommand command;
command.set(&wreq);
boost::system::error_code ec;
socket.io_control(command, ec);
if (ec)
{
// An error occurred.
}
Custom command:
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
namespace io_control {
// I/O control command for getting number of bytes available.
class myCommand
{
public:
// Default constructor.
myCommand()
: value_(0)
{
}
// Get the name of the IO control command.
int name() const
{
return static_cast<int>(SIOCGIWESSID);
}
// Set the value of the I/O control command.
void set(struct iwreq* value)
{
value_ = static_cast<detail::ioctl_arg_type>(value);
}
// Get the current value of the I/O control command.
std::size_t get() const
{
return static_cast<struct iwreq*>(value_);
}
// Get the address of the command data.
detail::ioctl_arg_type* data()
{
return &value_;
}
// Get the address of the command data.
const detail::ioctl_arg_type* data() const
{
return &value_;
}
private:
detail::ioctl_arg_type value_;
};
} // namespace io_control
} // namespace detail
} // namespace asio
} // namespace boost
However, the code does not work.
If you have any example code or solution, please let me know.
Thank you.
I got this function
array<ItemType>^ GetNextItems(int n) {
auto ret = gcnew Collections::Generic::List < ItemType > ;
for (int i = 0; i < n; i++) {
auto item = GetNextItem();
if (item == ItemType()) break;
ret->Add(item);
}
return ret->ToArray();
}
But the compile gives me an error: cannot convert from 'cli::array< ItemType,1 > ^' to 'cli::array< ItemType,1 > ^'
ItemType is a template parameter ie.
generic <typename ItemType>
I've been staring at this for a while, I can't detect the fault. Why won't it compile?
If ItemType is a .NET/CLR type, then you'll need the ^-hat inside the return type declaration. The ^ is still not included in the actual type declaration.
So it would be something like this:
generic <typename ItemType>
ref class Test
{
array<ItemType ^>^
GetNextItems(int n)
{
List<ItemType ^> ^ ret = gcnew List<ItemType ^>(n);
...
return ret->ToArray();
}
};
Notice the added caret inside the <ItemType ^> return type declaration, but not in the class' generic definition.
Does anyone have a working, step-by-step example of how to implement IEnumerable and IEnumerator in C++/CLI? Alternatively, does someone know how to fix the following code from MS Connect which does not compile in Visual Studio 2005?
http://connect.microsoft.com/VisualStudio/feedback/details/101089/how-to-implement-ienumerable-t-and-ienumerable-c-cli
using namespace System;
using namespace System::Collections::Generic;
generic <class T>
public ref struct MyArray : public IEnumerable<T>
{
MyArray( array<T>^ d )
{
data = d;
}
ref struct enumerator : IEnumerator<T>
{
enumerator( MyArray^ myArr )
{
colInst = myArr;
currentIndex = -1;
}
bool MoveNext()
{
if( currentIndex < colInst->data->Length - 1 )
{
currentIndex++;
return true;
}
return false;
}
property T Current
{
T get()
{
return colInst->data[currentIndex];
}
};
// This is required as IEnumerator<T> also implements IEnumerator
property Object^ Current2
{
virtual Object^ get() new sealed = System::Collections::IEnumerator::Current::get
{
return colInst->data[currentIndex];
}
};
void Reset() {}
~enumerator() {}
MyArray^ colInst;
int currentIndex;
};
array<T>^ data;
IEnumerator<T>^ GetEnumerator()
{
return gcnew enumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() new sealed = System::Collections::IEnumerable::GetEnumerator
{
return gcnew enumerator(this);
}
};
int main()
{
int retval = 0;
MyArray<int>^ col = gcnew MyArray<int>( gcnew array<int>{10, 20, 30 } );
for each( Object^ c in col )
{
retval += (int)c;
}
retval -= 10 + 20 + 30;
Console::WriteLine("Return Code: {0}", retval );
return retval;
}
The compiler is unable to find the enumerator method implementations:
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'bool System::Collections::IEnumerator::MoveNext(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'void System::Collections::IEnumerator::Reset(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>::enumerator' must provide an implementation for the interface method 'T System::Collections::Generic::IEnumerator<T>::Current::get(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 55
error C3766: 'MyArray<T>' must provide an implementation for the interface method 'System::Collections::Generic::IEnumerator<T> ^System::Collections::Generic::IEnumerable<T>::GetEnumerator(void)' c:\Projects\VCNET\2005\IEnumerable\IEnumerable\IEnumerable.cpp 68
This compiles for me without a single warning (on VS2010):
using namespace System;
using namespace System::Collections::Generic;
generic <class T>
public ref struct MyArray : public IEnumerable<T>
{
MyArray( array<T>^ d )
{
data = d;
}
ref struct enumerator : IEnumerator<T>
{
enumerator( MyArray^ myArr )
{
colInst = myArr;
currentIndex = -1;
}
virtual bool MoveNext() = IEnumerator<T>::MoveNext
{
if( currentIndex < colInst->data->Length - 1 )
{
currentIndex++;
return true;
}
return false;
}
property T Current
{
virtual T get() = IEnumerator<T>::Current::get
{
return colInst->data[currentIndex];
}
};
// This is required as IEnumerator<T> also implements IEnumerator
property Object^ Current2
{
virtual Object^ get() = System::Collections::IEnumerator::Current::get
{
return colInst->data[currentIndex];
}
};
virtual void Reset() = IEnumerator<T>::Reset {}
~enumerator() {}
MyArray^ colInst;
int currentIndex;
};
array<T>^ data;
virtual IEnumerator<T>^ GetEnumerator()
{
return gcnew enumerator(this);
}
virtual System::Collections::IEnumerator^ GetEnumerator2() = System::Collections::IEnumerable::GetEnumerator
{
return gcnew enumerator(this);
}
};
int main()
{
int retval = 0;
MyArray<int>^ col = gcnew MyArray<int>( gcnew array<int>{10, 20, 30 } );
for each( Object^ c in col )
{
retval += (int)c;
}
retval -= 10 + 20 + 30;
Console::WriteLine("Return Code: {0}", retval );
return retval;
}