I am reading data from bluetooth gatt characteristic. First data is one byte and I am successfully reading it by code:
val strValue = characteristic.value[0].toUByte()
characteristic.value[1] contains most significant byte of uint16
characteristic.value[2] contains least significant byte of uint16
What I want to do is get uint16 and put it into strValue.
I've tried to use shl function but it brings me this error:
IMAGE1
I also tried this:
IMAGE2
How to proper do this in Kotlin? I am good in C but Kotlin is new for me.
Solution:
val strValue :UShort = (characteristic.getIntValue(FORMAT_UINT16,1) or characteristic.getIntValue(FORMAT_UINT16,2).shl(8)).toUShort()
Related
I wanted to know what is the correct way to convert a managed array<unsigned char>^ to an unmanaged std::string. What I do right now is this:
array<unsigned char>^ const content = GetArray();
auto enc = System::Text::Encoding::ASCII;
auto const source = enc->GetString(content);
std::string s = msclr::interop::marshal_as<std::string>(source);
Is there a way to marshal the content in one step to a std::string without converting to a String^?
I tried:
array<unsigned char>^ const content = GetArray();
std::string s = msclr::interop::marshal_as<std::string>(content);
but this gave me following errors:
Error C4996 'msclr::interop::error_reporting_helper<_To_Type,cli::array<unsigned char,1> ^,false>::marshal_as':
This conversion is not supported by the library or the header file needed for this conversion is not included.
Please refer to the documentation on 'How to: Extend the Marshaling Library' for adding your own marshaling method.
Error C2065 '_This_conversion_is_not_supported': undeclared identifier
If the array is of plain bytes, then it's already ASCII encoded (or whatever narrow characters you're using). Converting to a managed UTF-16 String^ is an unnecessary detour.
Just construct a narrow-characters string from the byte array. Pass a pointer to the first byte and the length.
array<unsigned char>^ const content = GetArray();
pin_ptr<unsigned char> contentPtr = &content[0];
std::string s(contentPtr, content->Length);
I'm not at a compiler right now, there may be trivial syntax errors.
I have a "CLock.dll" have some functions
For example: This is document for a function
__int16 __stdcall dv_get_auth_code(unsigned char* auth);
Function
To gain authorization code of setup card.
Parameters
auth:[out] Return authorization code, 6 characters.
Return
Succeed then return 0.
I need to call this dll in my winform application. I try
[DllImport("CLock.dll",CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int dv_get_auth_code([Out]StringBuilder auth);`
and in Main()
My code:
StringBuilder sb = new StringBuilder();
int result = dv_get_auth_code(sb);
But it's working. What should i do? Thank you and have a nice day !
There are two mistakes in the code as presented. The return type is wrong, and no buffer is allocated.
The return type is a 16 bit type, in C# that is short:
[DllImport("Clock.dll")]
public static extern short dv_get_auth_code(StringBuilder auth);
Then to call the function you need to allocate a buffer. I don't know how large that buffer should be, presumably you know that.
StringBuilder sb = new StringBuilder(bufferLengtg);
short result = dv_get_auth_code(sb);
It is always wise for such an API to pass the length of the buffer to the function. Then it can make sure it does not overrun the buffer.
I haven't seen C++ code in more than 10 years and now I'm in the need of developing a very small DLL to use the Ping class (System::Net::NetworkInformation) to make a ping to some remoteAddress.
The argument where I'm receiving the remoteAddress is a FREObject which then needs to be transformed into a const uint8_t *. The previous is mandatory and I can't change anything from it. The remoteAddress has to be received as a FREObject and later be transformed in a const uint8_t *.
The problem I'm having is that I have to pass a String^ to the Ping class and not a const uint8_t * and I have no clue of how to convert my const uint8_t * to a String^. Do you have any ideas?
Next is part of my code:
// argv[ARG_IP_ADDRESS_ARGUMENT holds the remoteAddress value.
uint32_t nativeCharArrayLength = 0;
const uint8_t * nativeCharArray = NULL;
FREResult status = FREGetObjectAsUTF8(argv[ARG_IP_ADDRESS_ARGUMENT], &nativeCharArrayLength, &nativeCharArray);
Basically the FREGetObjectAsUTF8 function fills the nativeCharArray array with the value of argv[ARG_IP_ADDRESS_ARGUMENT] and returns the array's length in nativeCharArrayLength. Also, the string uses UTF-8 encoding terminates with the null character.
My next problem would be to convert a String^ back to a const uint8_t *. If you can help with this as well I would really appreciate it.
As I said before, non of this is changeable and I have no idea of how to change nativeCharArray to a String^. Any advice will help.
PS: Also, the purpose of this DLL is to use it as an ANE (Air Native Extension) for my Adobe Air app.
You'll need UTF8Encoding to convert the bytes to characters. It has methods that take pointers, you'll want to take advantage of that. You first need to count the number of characters in the converted string, then allocate an array to store the converted characters, then you can turn it into System::String. Like this:
auto converter = gcnew System::Text::UTF8Encoding;
auto chars = converter->GetCharCount((Byte*)nativeCharArray, nativeCharArrayLength-1);
auto buffer = gcnew array<Char>(chars);
pin_ptr<Char> pbuffer = &buffer[0];
converter->GetChars((Byte*)nativeCharArray, nativeCharArrayLength-1, pbuffer, chars);
String^ result = gcnew String(buffer);
Note that the -1 on nativeCharArrayLength compensates for the zero terminator being included in the value.
I am trying to convert a handle string to a normal string. I though the method I was using was working, but when I look in the debugger it appears that half of my string has been chopped off on the line that creates the chars variable. Any idea why and what the proper way to convert a handle string to a normal string woudl be?
std::string convert(String^ s) {
const char* chars = (const char*)(System::Runtime::InteropServices::Marshal::
StringToHGlobalAnsi(s)).ToPointer();
string myNewString = std::string(chars);
return myNewString;
}
It's probably the debugger that's cutting off the display of the string. You didn't mention how long a string you're using, but the debugger can't display infinite length, so it has to cut it off at some point.
To verify this, try printing myNewString to the console, or to the debugger via Debug::WriteLine or OutputDebugString.
However, there is a significant issue in your code: After allocating memory with StringToHGlobalAnsi, you must free it using FreeHGlobal.
If you want to continue using StringToHGlobalAnsi, I'd fix it up like this:
std::string convert(String^ s) {
IntPtr ptr = Marshal::StringToHGlobalAnsi(s);
string myNewString = std::string((const char*)ptr.ToPointer());
Marshal::FreeHGlobal(ptr);
return myNewString;
}
However, it's probably easier to use the marshal_as methods. This will take care of everything for you.
std::string output = marshal_as<std::string>(managedString);
I am working on an app that deals with external hardware communication, and I'm having problem getting checksum of a package. (I'm still learning objective C while making this app, so I'm still fairly new in this.)
In another code written in C, the checksum was calculated like this:
byte CalculateCheckSum (byte txcount){
byte local_cs=0;
while(txcount>0){
local_cs+=*x_ptr;
x_ptr += 1;
txcount--;
};
return (~local_cs+1);
}
I tried to use the some code for objective C:
u_int8_t synByteSOH[]= {SYN,SYN,SOH,SETSERIALINFO};
- (Byte)CalcCheckSum:(Byte)i
{ u_int8_t synByteSOH[]= {SYN,SYN,SOH,SETSERIALINFO};
Byte local_cs = 0;
int j = 0;
while (i>0) {
local_cs += synByteSOH[j];
i--;
j++;
};
return (~local_cs+1);
}
No warnings or errors, but it's said clang: error: linker command failed with exit code 1
Does anyone know why is that? And how should I fix it?
All valid C code it valid Objective C code. Don't try rewriting it into a Objective C method - there's zero value to that.
The trick to adapting the original function is that it relies on several things: byte being typedeffed, and a global/static variable called x_ptr.
About x_ptr, where it comes from and how is it initialized in the original, we know nothing from the pasted snippet. So assuming that the byte array synByteSOH is the data block you need a checksum of, just introduce a file static variable x_ptr of type byte* and initialize it to your data block:
typedef unsigned char byte;
static byte *x_ptr;
byte CalculateCheckSum (byte txcount)
//...Follows as pasted
//...
//And now we call it elsewhere:
byte synByteSOH[]= {SYN,SYN,SOH,SETSERIALINFO};
x_ptr = synByteSOH
byte Checksum = CalculateCheckSum(4); //4 is the data block size
In general, even in an ObjC project it's perfectly OK to have C functions. No one ever said every piece of code should be in a class method.