Getting a String Argument From Node Add On - c++

I am trying to pass a string to a C++ add on in Node.js. I am using the Nan library as seems to be recommended. For the equivalent task with a number I do the following:
NAN_METHOD(funcName) {
if (!info[0]->IsUint32()) {
Nan::ThrowError("Argument must be an unsigned int 32");
}
v8::Local<v8::Context> ctxt = info.GetIsolate()->GetCurrentContext();
uint32_t blocks;
info[0]->Uint32Value(ctxt).To(&blocks);
}
after which I can work with the blocks variable. There doesn't seem to be any equivalent StringValue function. I have tried info[0]->ToString(ctxt) but this gives me a MaybeLocal which seems to be a null check around local. Once I convert to v8::Local<v8::String> I have no idea how to actually access the string value. I have also tried info[0]->Cast but this also does not work. Any help would be appreciated.

Do not forget that V8 stores internally all strings as UTF-16 unlike most other languages/frameworks which use UTF-8.
Here is a sample code:
if (info.Length() < num + 1) {
Nan::ThrowError(name " must be given");
return;
}
if (!info[num]->IsString()) {
Nan::ThrowTypeError(name " must be a string");
return;
}
std::string var = (*Nan::Utf8String(info[num]));
You can check this which has many defines for decoding various values passed to a NaN C++ method from JS:
https://github.com/mmomtchev/node-gdal-async/blob/983a5df62ceb85f8c1fb580d6d7d496f38db36cd/src/gdal_common.hpp#L429

Related

How to convert fetched string data to character array?

I am doing this IoT based project on displaying data to connected display( I've used the MAX7219 module, in this case) with the help of nodeMCU. The idea here is that the string which is stored in my firebase database is to be display on the led display.
I've had no trouble in getting the value from the database to my nodeMCU but there is this little problem with converting that string to char array since the code i am using( Max72xx_Message_serial, which was available as an example with the max72xx library) has used char array but i can only fetch the stored data in string format. I've modified that code so as to connect with firebase but the main issue is to convert the string fetched from the database to char array.
I tried toCharArray() but it still shows conversion error.
void readfromfirebase(void)
{
static uint8_t putIndex = 0;
int n=1;
while (Firebase.available())
{
newMessage[putIndex] = (char)Firebase.getString("Submit Message"); // this line produces the error
if ((newMessage[putIndex] == '\n') || (putIndex >= BUF_SIZE-3)) // end of message character or full buffer
{
// put in a message separator and end the string
newMessage[putIndex++] = ' ';
newMessage[putIndex] = '\0';
// restart the index for next filling spree and flag we have a message waiting
putIndex = 0;
newMessageAvailable = true;
}
else if (newMessage[putIndex] != '\r')
// Just save the next char in next location
{putIndex++;}
n++;
}
}
I think you are confusing the types
getString returns a String object wich can be converted to a char[] using the methods of the String class.
I assume your newMessage is of type char[] or char*.
Then I would advise you to go for the String.c_str() method, because it returns a C style null-terminated string, meaning a char*.
See https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/c_str/ for reference.
It also sets the last character of the string to 0. So methods like strlen, strcmp etc will work.
! be carefull not to modify the array returned by c_str(), if you want to modify it you chould copy the char[] or use string.toCharArray(buf, len).
Your Code might then look like the following.
String msg = Firebase.getString("Submit Message");
newMessage = msg.c_str();
// rest of your code
If newMessage is a buffer storing multiple messages, meaning char* newMessage[3].
String msg = Firebase.getString("Submit Message");
newMessage[putIndex] = msg.c_str();
// rest of your code
Be careful, because you are storing multiple characters in an array, so use strcmp to compare these arrays!
If you are new to C I would recommend reading.
https://www.cprogramming.com/tutorial/c/lesson9.html
https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/ (as pointed out by #gre_gor)

Converting an int to a string for a to_string method C++

I am writing a lexical analyzer in C++ and have to include a to_string() method for my subclasses. This method won't be used by the lexical analyzer but we are told we have to include them for debugging purposes. The to_string methods I have written keep generating errors and I am not sure why. Here is what I have:
string *AddopToken::to_string()
{
token_type_type tokenType = get_token_type();
addop_attr_type addopAttr = get_attribute();
return "[TOKEN TYPE: " + tokenType + ", ATTRIBUTE TYPE: " + addopAttr + "]";
}
This seems like it should work, but for some reason it does not.
Here is the typedef for addop_attr_type in the AddopToken header.
typedef enum addop_attr { ADDOP_ADD = 400,
ADDOP_SUB = 401,
ADDOP_OR = 402,
ADDOP_NO_ATTR = 499 } addop_attr_type;
So even though the type of addopAttr is addop_attr_type, all that really is is an int constant. I figured C++ could convert an int to a string. Is there a way to convert these variables to a string so my to_string() will work correctly?
C++ doesn't allow + for concatenation of string literals or string literals with integers.
The code you need is
char buff[1204];
sprintf(buff, "[TOKEN_TYPE; %d , ATTRUBUTE_TYPE %d ]", tokenType, addopAttr);
return std::string(buff);
You don't have to use the old C function sprintf, there are also lots of C++ functions people have invented for achieving similar things, and that gets rid of the temporary buffer, but at cost of being harder to follow what is going on underneath.
This should work for you:
Edit: now it returns pointer to a string, Don't forget to delete the pointer after you finish using it.
std::string* AddopToken::to_string() const{
token_type_type tokenType = get_token_type();
addop_attr_type addopAttr = get_attribute();
std::string* result = std::string();
*result = std::string("[TOKEN TYPE: ") + std::to_string(tokenType) + std::string(", ATTRIBUTE TYPE: ") + std::to_string(addopAttr) + std::string("]");
return result;
}
C++ see "[TOKEN TYPE: " as char[14] and not as a string. And to convert int to string use std::to_string().

I can't convert cstring to int

I want to get int from cstring.
Here is Code.
CStringArray paramArray;
paramArray.Add((LPCSTR)"5");
paramArray.Add((LPCTSTR)"151");
pvarArguments = new CComVariant[2];
pvarArguments[0] = (LPCTSTR)paramArray[1];
CString str;
str = (CStringA)pvarArguments[0];
int nlen = _wtoi(str.GetBuffer());
When I run my program, I always get value 0, and I can't understand why it is.
Please help me.
From TFM (emphasis mine):
Each function returns the int value produced by interpreting the input
characters as a number. The return value is 0 for atoi and _wtoi, if
the input cannot be converted to a value of that type.
Print the string or examine it using a debugger. There may be invalid (including unprintable) characters in the string.
It's hard to tell even what you are trying to do. You do know that C++ arrays are 0-based, right? I ask because this line of code:
pvarArguments[0] = (LPCTSTR)paramArray[1];
is totally messed up. I don't understand why it's not throwing an exception when trying to index an element in a CStringArray that is equal to the count of elements. You can only index to count-1 ==>> which in this case is "0".
Your pvarArguments[0] will have junk in it--I have no idea why an exception wasn't thrown.
If you want to get a different type out of a variant, you can use VariantChangeType() and not mess with wcstoi or atoi. It will give an error code if it fails instead of just returning 0. If you are hell bent on using wcstoi or atoi on a CString, use _tstoi() which works whether you nave UNICODE defined or not.
CStringA implies ANSI string type which would require atoi not _wtoi.
I suggest:
CString str(pvarArguments[0]);
int nlen = atoi(str.GetString());
GetBuffer() is not ideal because you must remember to later ReleaseBuffer().
EDIT: In light of the new information, try this:
paramArray.Add(L"5");
paramArray.Add(L"151");
The L macro makes the string wchar_t aware. If L doesn't work try _T instead. And then use _wtoi or _tstoi.
CStringArray paramArray;
paramArray.Add(_T("5"));
paramArray.Add(_T("151"));
CComVariant *pvarArguments = new CComVariant[2];
pvarArguments[0] = (LPCTSTR)paramArray[1];
CString str;
str = pvarArguments[0].bstrVal;
int nlen = _ttoi(LPCTSTR(str));
per suggestion above, this compiles for me:
rs->GetFieldValueString(0).Left(1) == sBoroCode
&& (_ttoi(LPCTSTR(sLowHouseNo)) % 2) == (_ttoi(LPCTSTR(rs->GetFieldValueString(2))) % 2)

CFile writes some garbage value

Im wriitng some data in File.But it doesnot write this properly.
Code:
CString sFileName = "C:\\Test.txt";
CFile gpFile;
CString testarr[10] = {"Tom","Ger","FER","DER","SIL","REM","FWE","DWR","SFE","RPOP"};
if (!gpFile.Open( sFileName,CFile::modeCreate|CFile::modeWrite))
{
AfxMessageBox( sFileName + (CString)" - File Write Error");
return;
}
else
{
gpFile.Write(testarr,10);
}
AfxMessageBox("Completed");
gpFile.Close();
It shows the file as
That's probably because you're using CFile incorrectly. The first parameter to CFile::Write should be a buffer whose bytes you'd like to write to the file. However, testarr is more like a "buffer of buffers", since each element of testarr is a string, and a string is itself a sequence of bytes.
What you would need to do instead is either concatenate the elements of testarr, and then call CFile::Write. Or (probably more practical), iterate over testarr printing each string one at a time, e.g. for your particular example, the following should do what you're looking for:
for(int i = 0; i < 10; ++i)
{
gpFile.Write(testarr[i], strlen(testarr[i]));
}
There may be some built-in way to accomplish this, but I'm not really familiar with MFC, so I won't be much help there.

DragonFire SDK NetSend Response

I recently pruchased DragonFire SDK and I'm having a slight problem. I am using a NetSend function to send details to my PHP Script on my server and it is returning the correct information, but with a slight 'twist' to it. This is my PHP Script:
<?php
$email = isset($_GET['email']) ? $_GET['email'] : "";
$password = isset($_GET['password']) ? $_GET['password'] : "";
if ($email == "tom") {
echo 1;
} else {
echo 0;
}
?>
And this is the C++ I'm using:
int login_response(int event, char *response, int length) {
printf(response);
return event;
}
The response is:
0ýýýý««««««««
Unless I enter 'tom' as the email, then it's:
1ýýýý««««««««
I'm not sure why it is doing this at all.
To elaborate on the previous answer, C and C++ assume that strings are terminated with a null (\0), so functions like printf() will expect that; but DragonFireSDK's NetSend doesn't always use this convention, and it assumes you're going to look at the value in the length variable. The above code simply forces the null to be in place for printf()'s benefit.
That may not be the safest solution. You don't know that the block of memory that NetSend is sending to the callback is something you can safely write to, even if you then restore the original value when you're done, as is done above. The most bulletproof approach would be to copy the string to somewhere else like a local variable only to the length specified, if you have to use printf(); or, better yet, just use the data where it is but only read it, if you don't need to go to printf(). For instance, here's a clumsy but safe version:
char *cp;
for (cp = response; cp-response < length; cp++) {
printf("%c",*cp);
}
printf("\n");
However, this is probably being paranoid. I doubt this or any other version of DragonFireSDK is likely to use a buffer you can't safely write to.
int OnResponse(int event, char *response, int length)
{
int resvalue = response[length];
response[length] = 0;
printf(response);
response[length] = resvalue;
return event;
}