How are enums defined in Preon? - preon

I am trying to use the preon I compiled from github (v 1.1) to parse the messages I get from an embedded C++ application. I included antlr 3.3-complete version in my project. I defined the following class as a header for network messages:
public class Header {
#BoundNumber(byteOrder = org.codehaus.preon.buffer.ByteOrder.BigEndian)
public MessageType MsgType;
#BoundNumber(byteOrder = org.codehaus.preon.buffer.ByteOrder.BigEndian)
public int MsgNo;
#BoundNumber(byteOrder = org.codehaus.preon.buffer.ByteOrder.BigEndian)
public int RspNo;
#BoundNumber(byteOrder = org.codehaus.preon.buffer.ByteOrder.BigEndian)
public int Length;
}
MessageType enum is as follows:
public enum MessageType{
#BoundEnumOption(0x0000) Dummy1,
#BoundEnumOption(0x0001) Dummy2
}
I try to cast the received network buffer as following:
Codec<Header> headerCodec = Codecs.create(Header.class);
Header h = Codecs.decode(headerCodec, headerData);
System.out.println(h);
I get the following antlr error. Is there something wrong with my definitions, or my included packages?
line 1:0 no viable alternative at input '< EOF >'
Thanks

I found the problem. It seems for enumerations you have to explicitly provide a size value in BoundNumber annotation as following:
#BoundNumber(ByteOrder.BigEndian, size="32")
public MessageType MsgType;

Related

C# - Method's type signature is not PInvoke compatible

I am trying to use the VC++ (2003) dll in C# (2010)
When am calling the method of dll from c# am getting this error
"Method's type signature is not PInvoke compatible"
I am returning the structure from VC++
Code:
struct SLFData
{
public:
char ByLat[10];
char ByLong[10];
};
And I am marshalling in C#
Code:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SLFData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public char[] ByLat;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public char[] ByLong;
};
Yet again I get the same error!
What am I missing here?
Can anybody help me Plzz
You say that you are using the struct as a return value. The documentation says:
Structures that are returned from platform invoke calls must be blittable types. Platform invoke does not support non-blittable structures as return types.
Your struct is not blittable. So you cannot use it as a function return type.
The simplest way to proceed is to return the struct via a parameter of the function. Change the C++ function to accept a parameter of type SLFData* and have the caller pass in the address of a struct which the C++ function populates. On the C# side you pass the struct as an out parameter.
FWIW, your struct declaration is wrong. For a start C# char is two bytes wide. It's best done like this:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SLFData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string ByLat;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string ByLong;
};

Error assigning value to a static variable

In this piece of code I don't know why the compiler doesn't let me assign the value 0 to variable x. I highlighted the line that cause the problem.
class List{
private:
int p;
public:
static int x;
void total();
};
void List::total(List *a){
x + = a -> p;
cout<<x;
getch();
x=0; // problem here
}
I also noticed that if I write int List::sum=0 before the function body, program works just fine. I just don't understand why.
I appreciate any help!
You have declared the static in your class but have not defined a variable for it.
class List{
private:
int p;
public:
static int x; // this is just a declaration
void total();
};
You need to define it, normally in the associated cpp file:
List::x = 0; // define variable and initialise
Quoting from here:
9.4.2 Static data members
The declaration of a static data member in its class definition is
not a definition and may be of an incomplete type other than
cv-qualified void. The definition for a static data member
shall appear in a namespace scope enclosing the member's class
definition. In the defi- nition at namespace scope, the name of the
static data member shall be qualified by its class name using the ::
operator. The initializer expression in the definition of a
static data member is in the scope of its class
(basic.scope.class).
The operator += tries to increase the value of x. You need to initialize x before using it.

How to properly create a property to store any amount of values?

Making the shift from C++ to C++/CX I stumbled upon that ref classes can't have native members in they're public or protected members, due to possible errors with java and stuff. Instead we now have to use properties, which I can make but only to hold 1 value...
The idea was to make a property that would store 4 floats in an array or vector and later pass the values to a XMVECTOR. The relevant code I have in the class header file until now is:
public:
property std::vector<float> num{
void set(std::vector<float> e){
NUM = e;
};
std::vector<float> get(){
return NUM;
};
};
private:
std::vector<float> NUM;
Later in the .cpp file I do:
std::vector<float> g;
g.pushback(3);
num = g;
I also make it a string to pass to a TextBox(but that's not important). In the end I just get many similar errors... The 2 errors are:
error C3986: 'set': signature of public member contains native type 'std::vector<_Ty>'
error C3986: 'set': signature of public member contains native type 'std::allocator<_Ty>'
The only thing I imagine is that I can't use strings or vectors. I know Platform::Strings exist but what about vectors??
Standard C++ types cannot be projected across the WinRT ABI, which is the communication layer shared by all WinRT language projections (C#/VB/JS). As Jagannath mentions, there is a collection interface (Windows::Foundation::Collections::IVector<T>). There is also a dictionary type (IMap<K,V>) and various iterators and support types. These are understood by all languages, but are just interfaces. Each language projection is responsible for authoring runtime classes that implement these interfaces. For C++/Cx, these ref classes are found in the header <collection.h> and are in the namespace Platform::Collections. Platform::Collections::Vector<T> and Platform::Collections::Map<K,V> are the basic types you can use as backing stores. Additionally, Vector<T> can be move-constructed from std::vector<T>.
However, you can't make a public property of type Platform::Collections::Vector<T> either, as this is still a C++ type. What you do instead is create a public property of type Windows::Foundation::Collection::IVector<T> which is backed by a private member variable of type Platform::Collections::Vector<T>.
Essentially:
public:
property Windows::Foundation::Collections::IVector<float>^ num{
Windows::Foundation::Collections::IVector<float>^ get(){
return NUM;
}
}
private:
Platform::Collections::Vector<float>^ NUM;
I have avoided mentioning the property setter, because that gets tricky (your private type would need to also be an IVector and it will only be a Platform::Collections::Vector if it came from C++).
You could use Windows::Foundation::Collections::IVector<float>^ for the signatures. I could not test this as I don't have the compiler at hand.
Hey guys I managed to get this working so I thought I'll post the code. The header file goes like this:
public:
property Windows::Foundation::Collections::IVector<int>^ num{
void set(Windows::Foundation::Collections::IVector<int>^ e){
NUM = safe_cast<Platform::Collections::Vector<int>^>(e);
};
Windows::Foundation::Collections::IVector<int>^ get(){
return NUM;
};
};
private:
Platform::Collections::Vector<int>^ NUM;
And in the .cpp file the code is:
num = ref new Vector<int>;
num->Append(5);
num->Append(54);
TextBox1->Text = num->GetAt(0).ToString() + "\n" + num->GetAt(1).ToString();
The result will have written the values 5 and 54 to a TextBox.

Working with vector values in C++ CLI

Here is my header file in Visual C++ Express 2010 (note the last line):
/* custom class header to communicate with LynxMotion robot arm */
using namespace System;
using namespace System::IO::Ports;
public ref class LynxRobotArm
{
public:
LynxRobotArm();
~LynxRobotArm();
void connectToSerialPort(String^ portName, int baudRate);
void disconnectFromSerialPort();
void setCurrentPosition(int channel, int position);
int getCurrentPosition(int channel);
void moveToPosition(int channel, int position);
private:
void initConnection();
SerialPort^ serialPort;
array<String^> ^serialPortNames;
String^ portName;
int baudRate;
std::vector<int> *currentPosition;
};
I try to assign a value to the vector by using this function;
void LynxRobotArm::setCurrentPosition(int channel, int position)
{
currentPosition[channel] = position;
}
The compiler gives me an error C2679:
binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion)
I looked up at MSDN and they say:
To use the operator, you must overload it for the specified type or define a conversion to a type for which the operator is defined.
I tried using currentPosition.at(channel) = position but it did not make a difference.
I am stuck... quite new to pointers, noted that using std::vector<int> currentPosition; instead of std::vector<int> *currentPosition; does not compile.
How should my set-function work? (will try getter afterwards..)

Can extension methods modify extended class values?

I was just trying to code the following extension method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace _4Testing
{
static class ExtensionMethods
{
public static void AssignMe(this int me, int value)
{
me = value;
}
}
}
But it is not working, i mean, can I use an extension method to alter values from extended classes? I don't want to change void return type to int, just changing extended class value. Thanks in advance
Your example uses int, which is a value type. Classes are reference types and behaves a bit differently in this case.
While you could make a method that takes another reference like AssignMe(this MyClass me, MyClass other), the method would work on a copy of the reference, so if you assign other to me it would only affect the local copy of the reference.
Also, keep in mind that extension methods are just static methods in disguise. I.e. they can only access public members of the extended types.
public sealed class Foo {
public int PublicValue;
private int PrivateValue;
}
public static class FooExtensions {
public static void Bar(this Foo f) {
f.PublicValue = 42;
// Doesn't compile as the extension method doesn't have access to Foo's internals
f.PrivateValue = 42;
}
}
// a work around for extension to a wrapping reference type is following ....
using System;
static class Program
{
static void Main(string[] args)
{
var me = new Integer { value = 5 };
int y = 2;
me.AssignMe(y);
Console.WriteLine(me); // prints 2
Console.ReadLine();
}
public static void AssignMe(this Integer me, int value)
{
me.value = value;
}
}
class Integer
{
public int value { get; set; }
public Integer()
{
value = 0;
}
public override string ToString()
{
return value.ToString();
}
}
Ramon what you really need is a ref modifier on the first (i.e. int me ) parameter of the extension method, but C# does not allow ref modifier on parameters having 'this' modifiers.
[Update]
No workaround should be possible for your particular case of an extension method for a value type. Here is the "reductio ad absurdum" that you are asking for if you are allowed to do what you want to do; consider the C# statement:
5.AssignMe(10);
... now what on earth do you think its suppose to do ? Are you trying to assign 10 to 5 ??
Operator overloading cannot help you either.
This is an old post but I ran into a similar problem trying to implement an extender for the String class.
My original code was this:
public static void Revert(this string s)
{
char[] xc = s.ToCharArray();
s = new string(xc.Reverse());
}
By using the new keyword I am creating a new object and since s is not passed by reference it will not be modified.
I changed it to the following which provides a solution to Ramon's problem:
public static string Reverse(this string s)
{
char[] xc = s.ToCharArray();
Array.Reverse(xc);
return new string(xc);
}
In which case the calling code will be:
s = s.Reverse();
To manipulate integers you can do something like:
public static int Increment(this int i)
{
return i++;
}
i = i.Increment();

Resources