I started making tests where i check bytes but i noticed that I can't write byte in DataRow, because I get a message: System.ArgumentException: Object of type 'System.Int32' cannot be converted to type 'System.Byte'.
How can I convert int to byte in DataRow?
[DataRow(12, 12)]
[DataRow(23, 23)]
public void Consturcot_1param(byte h, byte expectedH)
{
Time t = new Time(h);
AssertTime(t, expectedH, expectedM: 0, expectedS: 0);
}
The simplest solution would be to cast int to byte:
[DataRow((byte)12, (byte)12)]
[DataRow((byte)23, (byte)23)]
public void TestMethod(byte h, byte expectedH)
{ }
Related
I have a mock for a c function
int Eeprom_WriteBuffer(uint32_t address, uint8_t *data, uint16_t data_len)
{
return mock("eeprom").actualCall("Eeprom_WriteBuffer")
.withParameter("address", address)
.withParameter("data", data)
.withParameter("data_len", data_len)
.withOutputParameter("data", data)
.returnIntValueOrDefault(-1);
}
The function is that I provide it some byte array and it writes this to eeprom.
I want to be able to test that the data my man in the middle function passed down to the mock is what I expect.
eg
TEST (TestGroup, Test)
{
uint8_t data[424];
for (unsigned char & i : data)
i = rand() % UINT8_MAX;
uint8_t actual_data[sizeof(data)];
mock("eeprom").expectOneCall("Eepriom_WriteBuffer")
.withParameter("address", 0)
.<GET THE DATA OUT TO TEST>("data", actual_data, sizeof(actual_data))
.andReturnValue(sizeof(data));
ManInTheMiddle(data, sizeof(data));
MEMCMP_EQUAL(data, actual_data, sizeof(data));
}
Is this possible with this framework or am I going to have to create some buffers to be able to pull the actual data from?
I'm trying to deserialize a Json object using the ArduinoJson 6 library. The object is passing through a mqtt callback using the PubSubClient library. The payload contains the following example: "{\"action\":\"message\",\"amount\":503}" but I am unable to retrieve the amount value. Only zeros are returned when using the following:
void messageReceived(char *topic, byte *payload, unsigned int length)
{
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload, length);
const int results = doc["amount"];
Serial.print(results);
}
This works and returns 503 as needed:
DynamicJsonDocument doc(1024);
char json[] = "{\"action\":\"message\",\"amount\":503}";
deserializeJson(doc, json);
const int results = doc["amount"];
Serial.print(results);
I see the results of the payload when I use the following method:
void messageReceived(char *topic, byte *payload, unsigned int length)
{
for (unsigned int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
}
What is preventing me from being able to parse out the amount value from the first method?
When programming in C++, it always need to be aware the type of data that you are dealing with. The payload is a byte array, which is not what deserializeJson(doc, payload, length); is expecting, see the function signature of deserializeJson().
void messageReceived(char *topic, byte *payload, unsigned int length)
{
DynamicJsonDocument doc(128);
deserializeJson(doc, (char*) payload, length);
Serial.print(doc["amount"]);
}
Update & resolution:
The first method in my original post worked fine once I fixed the data that was being sent from the Lambda function to the IOT side. (Something I didn't include in my original question and didn't think it was relevant. Turns out it was.) Here is a snippet from the Lambda function that is receiving the data. The issue was that the data was being sent as a string and not parsed. Once I stringified the response and then parsed the output, it worked. Thank you #hcheung for the assistance and helpful info. Your suggestion works as well but only after I fixed the Lambda function.
async function sendToIOT(response) {
const data = JSON.stringify(response);
const iotResponseParams = {
topic: 'mythingname/subscribe',
payload: JSON.parse(data)
};
return iotdata.publish(iotResponseParams).promise()
}
My question is nearly identical to this question, except that the linked question deals with char*, whereas I'm using std::string in my code. Like the linked question, I'm also using C# as my target language.
I have a class written in C++:
class MyClass
{
public:
const std::string get_value() const; // returns utf8-string
void set_value(const std::string &value); // sets utf8-string
private:
// ...
};
And this get's wrapped by SWIG in C# as follows:
public class MyClass
{
public string get_value();
public void set_value(string value);
}
SWIG does everything for me, except that it doesn't make an utf8 to utf16 string conversion during the calls to MyClass. My strings come through fine if they are representable in ASCII, but if I try passing a string with non-ascii characters in a round-trip through "set_value" and "get_value", I end up with unintelligible characters.
How can I make SWIG wrap UTF-8 encoded C++ strings in C#? n.b. I'm using std::string, not std::wstring, and not char*.
There's a partial solution on the SWIG sourceforge site, but it deals with char* not std::string, and it uses a (configurable) fixed length buffer.
With the help (read: genius!) of David Jeske in the linked Code Project article, I have finally been able to answer this question.
You'll need this class (from David Jeske's code) in your C# library.
public class UTF8Marshaler : ICustomMarshaler {
static UTF8Marshaler static_instance;
public IntPtr MarshalManagedToNative(object managedObj) {
if (managedObj == null)
return IntPtr.Zero;
if (!(managedObj is string))
throw new MarshalDirectiveException(
"UTF8Marshaler must be used on a string.");
// not null terminated
byte[] strbuf = Encoding.UTF8.GetBytes((string)managedObj);
IntPtr buffer = Marshal.AllocHGlobal(strbuf.Length + 1);
Marshal.Copy(strbuf, 0, buffer, strbuf.Length);
// write the terminating null
Marshal.WriteByte(buffer + strbuf.Length, 0);
return buffer;
}
public unsafe object MarshalNativeToManaged(IntPtr pNativeData) {
byte* walk = (byte*)pNativeData;
// find the end of the string
while (*walk != 0) {
walk++;
}
int length = (int)(walk - (byte*)pNativeData);
// should not be null terminated
byte[] strbuf = new byte[length];
// skip the trailing null
Marshal.Copy((IntPtr)pNativeData, strbuf, 0, length);
string data = Encoding.UTF8.GetString(strbuf);
return data;
}
public void CleanUpNativeData(IntPtr pNativeData) {
Marshal.FreeHGlobal(pNativeData);
}
public void CleanUpManagedData(object managedObj) {
}
public int GetNativeDataSize() {
return -1;
}
public static ICustomMarshaler GetInstance(string cookie) {
if (static_instance == null) {
return static_instance = new UTF8Marshaler();
}
return static_instance;
}
}
Then, in Swig's "std_string.i", on line 24 replace this line:
%typemap(imtype) string "string"
with this line:
%typemap(imtype, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") string "string"
and on line 61, replace this line:
%typemap(imtype) const string & "string"
with this line:
%typemap(imtype, inattributes="[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]", outattributes="[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Marshaler))]") string & "string"
Lo and behold, everything works. Read the linked article for a good understanding of how this works.
I'm puzzled by my own code :-) I'm trying to read data from PROGMEM. This works ok when I only have this array in PROGMEM. When adding an extra seperate array in PROGMEM it goes wrong. That is, when it's defined in a different piece of code and #included. When put together in 1 code it's fine. But I want these to arrays to live apart in different pieces of code.
I believe I have an error in the last function which I have include here (callMenuItemParaName).
It has to do with the way I'm reading out PROGMEM. I think it's best to use memcpy_P but cannot find any online explanation on how to use this exactly.
The code I have now works, but as long as I don't put another array in PROGMEM. (this routine is working correctly, with the memcpy_P function. But how do I implement memcpy_P in the function callMenuItemParaName?
Thanks for any advice you can give! (ofcourse pgmspace.h is included)
Working on AVR GCC, IDE is Eclipse, mcu = atmega644 # 20MHz
unsigned char (*adresParaName);
const uint8_t TEXT0[] PROGMEM = "TEXT0";
const uint8_t paraNameAtk[] PROGMEM = "Atk ";
const uint8_t paraNameDcy[] PROGMEM = "Dcy ";
...
const uint8_t paraNameTru[] PROGMEM = "Tru ";
const uint8_t paraNameLight[] PROGMEM = "Light";
typedef void (*pMenu)(void);
typedef struct
{
void (*pointer2MenuNumber)(void);
char VALUE;
const unsigned char *adresParaName;
} sel_item;
const sel_item menuNumber2ItemDbase[] PROGMEM=
{
{ itemA , 0x00 , TEXT0 },
{ itemB , 0x01 , paraNameAtk },
{ itemC , 0x02 , paraNameDcy },
...
{ itemM , 0x05 , paraNameTru },
{ itemN , 0x05 , paraNameLight }
};
//prototypes
void callMenuItem(const sel_item *item);
void callMenuItemValue(const sel_item *item);
void callMenuItemParaName(const sel_item *item);
// *************************************************
// callMenu
// Description:
//
// *************************************************
void callMenuItem(const sel_item *item)
{
pMenu function = (pMenu)pgm_read_word(&item->pointer2MenuNumber);
function();
}
void callMenuItemValue(const sel_item *item)
{
setCursor(1,4);
char VAL = (char)pgm_read_byte(&item->VALUE);
char2LCD('0'+VAL);
}
void callMenuItemParaName(const sel_item *item)
{
char tempText[5];
char *data = (char*)pgm_read_word(&item->adresParaName);
strcpy_P (tempText, data);
for (uint8_t x=0;x<5;x++)
{
char2LCD(tempText[x]);
}
}
I've tried adding this:
char* pstr = 0;
memcpy_P (&pstr, data, sizeof(char*));
But no luck. (can't find a good tutorial on memcpy_P either, btw)
Your strings are 6 bytes long (remember the terminating 0), which means that you're overflowing tempText when you strcpy_P into it. Use memcpy_P instead.
memcpy_P(tempText, data, sizeof tempText);
The way you use pgm_read_word is just fine.
In C, you sometimes see something like:
struct foobar
{
int size;
int data[1];
};
where the data member doesn't really have just one element; rather it's meant to be variable length.
If you do something like that in D, is it going to let you, for example, read myfoobar.data[4]?
I know D has variable length arrays, e.g. int[] myvarlenintarray;, but what if you're trying to interface with some code that already puts out a data structure in memory like the one above, and possibly much more complex than that? Let's say it's in the first portion of int[3000] buffer;. Is there an easy way to cast it to a usable struct without moving it in memory? If not, is there an easy way to get the data into a similar struct without having to manually parse out each member of the struct?
edit:
I think I need to give a practical example so you see where I'm coming from.
import std.c.windows.windows;
import std.utf;
import std.stdio;
public struct REPARSE_DATA_BUFFER
{
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union
{
struct SymbolicLinkReparseBuffer
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR[1] PathBuffer;
}
SymbolicLinkReparseBuffer mySymbolicLinkReparseBuffer;
struct MountPointReparseBuffer
{
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR[1] PathBuffer;
}
MountPointReparseBuffer myMountPointReparseBuffer;
struct GenericReparseBuffer
{
UCHAR[1] DataBuffer;
}
GenericReparseBuffer myGenericReparseBuffer;
}
}
alias REPARSE_DATA_BUFFER* PREPARSE_DATA_BUFFER;
enum MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16*1024;
// Values for 'ReparseTag' member of REPARSE_DATA_BUFFER:
enum : DWORD {
IO_REPARSE_TAG_SYMLINK = 0xA000000C,
IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 // which also defines a Junction Point
}
enum DWORD FSCTL_GET_REPARSE_POINT = 0x000900a8;
enum FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000;
public extern(Windows) BOOL function(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPVOID, OVERLAPPED*) DeviceIoControl;
void main()
{
DeviceIoControl = cast(BOOL function(HANDLE, DWORD, LPVOID, DWORD, LPVOID, DWORD, LPVOID, OVERLAPPED*))GetProcAddress(LoadLibraryA("kernel32.dll"), "DeviceIoControl");
auto RPHandle = CreateFileW((r"J:\Documents and Settings").toUTF16z(), 0, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT + FILE_FLAG_BACKUP_SEMANTICS, null);
if (RPHandle == INVALID_HANDLE_VALUE)
{
printf("CreateFileW failed with error code %d.", GetLastError());
return;
}
BYTE[MAXIMUM_REPARSE_DATA_BUFFER_SIZE] reparsebuffer;
uint reparsedatasize;
auto getreparsepointresult = DeviceIoControl(RPHandle, FSCTL_GET_REPARSE_POINT, null, 0, cast(void*) reparsebuffer.ptr, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &reparsedatasize, null);
if (getreparsepointresult == 0)
{
printf("DeviceIoControl with FSCTL_GET_REPARSE_POINT failed with error code %d.", GetLastError());
return;
}
// Now what?
// If I do this:
auto ReparseDataPtr = cast(REPARSE_DATA_BUFFER*) reparsebuffer.ptr;
printf("%d == %d\n", reparsebuffer.ptr, ReparseDataPtr); // Alright, data hasn't been copied.
// But what good is a pointer? Can I use a pointer to a struct to access one of its members apart from dereferencing?
printf("%d == %d\n", &reparsebuffer[0], &(*ReparseDataPtr)); // Here, I dereference ReparseDataPtr, but nothing moves.
printf("%d == %d\n", &reparsebuffer[0], &((*ReparseDataPtr).ReparseTag)); // Same here, so I can access members in a roundabout way.
printf("%d == %d\n", &reparsebuffer[0], &(ReparseDataPtr.ReparseTag)); // And thanks to Jim's comment, here's a less roundabout way.
auto ReparseData = *ReparseDataPtr; // But if I assign a name to the dereferenced ReparseDataPtr,
printf("%d != %d\n", &reparsebuffer[0], &(ReparseData.ReparseTag)); // the data is copied to a new location, leaving most of PathBuffer behind.
REPARSE_DATA_BUFFER ReparseDataFn() {return *ReparseDataPtr;} // Similarly, this way
printf("%d != %d\n", &reparsebuffer[0], &(ReparseDataFn().ReparseTag)); // copies stuff to a new location.
}
Firstly, I don't understand why it's different for the case in which I don't give *ReparseDataPtr a name.
Secondly, is there no way to have a symbol whose type is REPARSE_DATA_BUFFER and whose data is located at reparsebuffer.ptr?
Have you tried doing the exact same thing in D as in C?
struct foobar { int size; int data[1]; };
It works... just use data.ptr instead of data to access the elements, because otherwise it will perform bounds checking with a length of 1.
You could access it via a helper method:
struct foobar
{
public:
int[] Data() { return data.ptr[0..size]; }
private:
int size;
int data[1];
}
You might also want to put int a static foreach over the members of foobar that uses static assert to make sure that the offset of each is less than the offset of data.