Copy from uchar vector to byte array [duplicate] - arrays

I'm trying to send an image from C++ to C# with an interop (marshaling) of C++ managed. image->getStream() return a const char* from a string.
I'm having exception with my Marshal::Copy function.
An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Am I doing the right thing for the copy from a const char* to a byte array ? My dll is compiled with ASCII char set in VS2010.
array<System::Byte>^ OsgViewer::getLastImage()
{
array< Byte >^ byteArray;
m_ImageQueue->lock();
int index = m_ImageQueue->getCurrentImageIndex();
std::shared_ptr<Image> image = m_ImageQueue->getImage(static_cast<unsigned int>(index));
if( image && image->isValid() == true)
{
int wLen = image->getStreamSize();
char* wStream = const_cast<char*>(image->getStream());
byteArray = gcnew array< Byte >(wLen);
// convert native pointer to System::IntPtr with C-Style cast
Marshal::Copy((IntPtr)wStream ,byteArray , 0, wLen);
}
m_ImageQueue->unlock();
return byteArray;
}
Image is a home made C++ class
class ADAPTER Image
{
public :
Image();
~Image();
const char* getStream() const;
int getStreamSize();
bool setStringStream(std::ostringstream* iStringStream);
void setIsValid(bool isValid){ m_isValid = isValid;}
bool isValid() const{return m_isValid;}
std::ostringstream* getOStringStream() {return m_StringStream;}
private:
std::ostringstream* m_StringStream;
bool m_isValid;
};

I wouldn't use Marshal::Copy. Since you have the array locally, why not just pin it and use memcpy?
pin_ptr<Byte> ptrBuffer = &byteArray[byteArray->GetLowerBound(0)];
You can now call memcpy to ptrBuffer.
When the scope ends the pinning is automatically undone.

Related

I have problem showing a float variable in an Arduino webserver

I am using Arduino Uno, ENC28j60. using rbbb_server example.
the library I am using: <EtherCard.h>
as can be seen in the code below I am trying to convert my Float var to Str using dtostrf() in the homepage function since emit_p() can not accept float vars. although Serial.println(temp1) is working correctly, but in the browser, I have a problem showing the variable(pic added). I've been looking for a solution but couldn't find any, unfortunately. would appreciate any suggestion.
#include <EtherCard.h>
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
static byte myip[] = { 192,168,1,203 };
byte Ethernet::buffer[500];
BufferFiller bfill;
static word homePage() {
String temp1;
float val = 311.322;
char s1[10];
temp1 = dtostrf(val,3,2,s1);
bfill = ether.tcpOffset();
bfill.emit_p(PSTR(
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n"
"\r\n"
"<meta http-equiv='refresh' content='1'/>"
"<title>RBBB server</title>"
"<h1>my val:$S</h1>"),
temp1);
Serial.println(temp1);
return bfill.position();
}
void setup () {
Serial.begin(57600);
if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
Serial.println(F("Failed to access Ethernet controller"));
ether.staticSetup(myip);
}
void loop () {
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if (pos)
ether.httpServerReply(homePage());
}
output in browser
I think I see your problem, but I can't test it.
dtostrf returns a char * pointer to the string you want to print here's the docs
It looks like that function is being called and assigning that string to the temp variable which is a String type (idk your experience, but working with text in Arduino can be very confusing check out this thread ).
Try changing temp1 to be a char * like this:
char * temp1;

How to get the class name of a window with C

Objective: Retrieve the class name of the current foreground window with plain C.
I have the following code to retrieve the class name:
PWSTR win_class = NULL;
GetClassNameW(hwnd,&win_class,MAX_PATH);
if(win_class != NULL)
free(win_class);
I am getting the following warnings:
warning C4047: 'function': 'LPWSTR' differs in levels of indirection
from 'PWSTR *' warning C4024: 'GetClassNameW': different types
for formal and actual parameter 2
I have two questions: How to solve those warnings, and how should I create an if condition to validate the result of the function GetClassName and set the value of win_class to "NOT FOUND" in case that the function does not find the class name?
The GetClassNameW() function does not allocate the memory needed for the returned class name - you have to do that (or simply provide automatic storage).
To check for success, simply test the return value of the function: if it succeeds, that will be the length of the class name string (in characters); if it fails, the value will be zero.
Here's a short, runnable program that gets the class name for the console window:
#include <Windows.h>
#include <stdio.h>
int main()
{
HWND hwnd = GetConsoleWindow();
wchar_t win_class[_MAX_PATH];
int status = GetClassNameW(hwnd, win_class, _MAX_PATH);
if (!status) wcscpy(win_class, L"NOT FOUND");
printf("%ls\n", win_class);
return 0;
}
When calling GetClassNameW(), you are passing a PWSTR* (wchar_t**) where a LPWSTR (wchar_t*) is expected. That is what the compiler is complaining about.
GetClassName() requires you to pre-allocate a character buffer and pass in a pointer to it, along with the buffer size. The function will not allocate a buffer and return a pointer back to you, like you are expecting. It will merely fill in your provided buffer as needed.
Try something more like this:
WCHAR win_class[256] = {0};
int win_class_len = 0;
HWND hwnd = GetForegroundWindow();
if (!hwnd)
{
// error handling as needed...
lstrcpyW(win_class, L"WINDOW NOT FOUND");
win_class_len = lstrlenW(win_class);
}
else
{
win_class_len = GetClassNameW(hwnd, win_class, 256);
if (win_class_len == 0)
{
DWORD err = GetLastError();
// error handling as needed...
lstrcpyW(win_class, L"CLASS NOT FOUND");
win_class_len = lstrlenW(win_class);
}
}
// use win_class as needed, up to win_class_len characters...
TCHAR is the universal char type working for Unicode and ANSI. GetClassName is the corresponding function replaced with GetClassNameA or GetClassNameW. If you need static string use TEXT() macro like TCHAR * s = TEXT("abc");
TCHAR win_class[MAX_PATH];
int res = GetClassName( hwnd, win_class, MAX_PATH );
if ( res > 0 )
// success
Your error is that win_class was unallocated (NULL) string pointer. GetClassName needs valid memory address of buffer.
You need to check if you function succseed. To do so, print the return value of the function.
Failiure will be presented by the value 0.

Swift: convert already allocated char array to char pointer

I am attempting to interface an existing C library to Swift 5.0.1 code on iOS. The C Header files have the following definitions:
char hostname[SFL_MAX_HOSTNAME_CHARS+1];
char os_release[SFL_MAX_OSRELEASE_CHARS+1];
int readHidCounters(HSP *sp, SFLHost_hid_counters *hid, char *hbuf, int hbufLen, char *rbuf, int rbufLen);
typedef struct _HSP {
[Many other elements omitted for brevity]
char hostname[SFL_MAX_HOSTNAME_CHARS+1];
char os_release[SFL_MAX_OSRELEASE_CHARS+1];
} HSP;
readHidCounters has an implementation (edited for brevity) like this:
int readHidCounters(HSP *sp, SFLHost_hid_counters *hid, char *hbuf, int hbufLen, char *rbuf, int rbufLen) {
int gotData = NO;
size_t len = hbufLen;
if(sysctlbyname("kern.hostname", hbuf, &len, NULL, 0) != 0) {
myLog(LOG_ERR, "sysctl(<kern.hostname>) failed : %s", strerror(errno));
}
else {
gotData = YES;
hid->hostname.str = hbuf;
hid->hostname.len = strlen(hbuf);
}
// UUID
memcpy(hid->uuid, sp->uuid, 16);
[...]
}
I have created an HSP struct and attempting to call readHidCounters in Swift like this
var sp = HSP()
[...]
readHidCounters(&sp,
&hidElem.counterBlock.host_hid,
&sp.hostname, // This is the error line
SFL_MAX_HOSTNAME_CHARS,
&sp.os_release,
SFL_MAX_OSRELEASE_CHARS)
I am attempting to pass in &sp.hostname results in the compiler error Cannot convert value of type '(Int8, Int8, Int8, [...], Int8)' to expected argument type 'Int8'. The problem is that hostname is a tuple of Int8's and I can't seem to get it properly converted to char *. I have tried various incarnations of UnsafeMutablePointer, withUnsafeMutablePointer and can't see how to get hostname properly recognized. Any suggestions greatly appreciated!
[Solved]
MartinR pretty much nailed it with his suggestion, but it did have a compiler error: Overlapping accesses to 'sp.hostname', but modification requires exclusive access; consider copying to a local variable. Updated code that compiles is
var myHostName = sp.hostname
var myOsRelease = sp.os_release
let _ = withUnsafeMutablePointer(to: &myHostName) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: sp.hostname)) {
hostNamePtr in
withUnsafeMutablePointer(to: &myOsRelease) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: sp.os_release)) {
osReleasePtr in
readHidCounters(&sp,
&hidElem.counterBlock.host_hid,
hostNamePtr, SFL_MAX_HOSTNAME_CHARS,
osReleasePtr, SFL_MAX_OSRELEASE_CHARS)
}
}
}
}
The “problem” is that C arrays are imported to Swift as tuples, and there is no simple method to treat a tuple as a Swift array, or get a pointer to the element storage (because a tuple can be inhomogeneous).
Similarly as in Converting a C char array to a String one can use the fact that Swift preserves the memory layout of structures imported from C, and with some pointer juggling and rebinding you'll get
let result = withUnsafeMutablePointer(to: &sp.hostname) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: sp.hostname)) {
hostNamePtr in
withUnsafeMutablePointer(to: &sp.os_release) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: sp.os_release)) {
osReleasePtr in
readHidCounters(&sp,
&hidElem.counterBlock.host_hid,
hostNamePtr, SFL_MAX_HOSTNAME_CHARS,
osReleasePtr, SFL_MAX_OSRELEASE_CHARS)
}
}
}
}
Another “trick” is to define C helper functions which return the array addresses as a pointers, and use the
SE-0044 Import as member
feature to make these helper functions available to Swift as computed properties. In the bridging header file you have to add
__attribute__((swift_name("getter:HSP.hostNamePtr(self:)")))
static inline char * _Nonnull hostNamePtr(HSP * _Nonnull hsp)
{
return hsp->hostname;
}
__attribute__((swift_name("getter:HSP.osReleasePtr(self:)")))
static inline char * _Nonnull osReleasePtr(HSP * _Nonnull hsp)
{
return hsp->os_release;
}
and then you can use these easily from Swift:
var sp = HSP()
let result = readHidCounters(&sp,
&hidElem.counterBlock.host_hid,
sp.hostNamePtr, SFL_MAX_HOSTNAME_CHARS,
sp.osReleasePtr, SFL_MAX_OSRELEASE_CHARS)
Try removing the & from the call, sp.hostname is already a pointer because it is an array, if it works you will have to remove the & from &sp.os_release too

Nanopb without callbacks

I'm using Nanopb to try and send protobuf messages from a VxWorks based National Instruments Compact RIO (9025). My cross compilation works great, and I can even send a complete message with data types that don't require extra encoding. What's getting me is the callbacks. My code is cross compiled and called from LabVIEW and the callback based structure of Nanopb seems to break (error out, crash, target reboots, whatever) on the target machine. If I run it without any callbacks it works great.
Here is the code in question:
bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
char *str = "Woo hoo!";
if (!pb_encode_tag_for_field(stream, field))
return false;
return pb_encode_string(stream, (uint8_t*)str, strlen(str));
}
extern "C" uint16_t getPacket(uint8_t* packet)
{
uint8_t buffer[256];
uint16_t packetSize;
ExampleMsg msg = {};
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
msg.name.funcs.encode = &encode_string;
msg.value = 17;
msg.number = 18;
pb_encode(&stream, ExampleMsg_fields, &msg);
packetSize = stream.bytes_written;
memcpy(packet, buffer, 256);
return packetSize;
}
And here's the proto file:
syntax = "proto2"
message ExampleMsg {
required int32 value = 1;
required int32 number = 2;
required string name = 3;
}
I have tried making the callback an extern "C" as well and it didn't change anything. I've also tried adding a nanopb options file with a max length and either didn't understand it correctly or it didn't work either.
If I remove the string from the proto message and remove the callback, it works great. It seems like the callback structure is not going to work in this LabVIEW -> C library environment. Is there another way I can encode the message without the callback structure? Or somehow embed the callback into the getPacket() function?
Updated code:
extern "C" uint16_t getPacket(uint8_t* packet)
{
uint8_t buffer[256];
for (unsigned int i = 0; i < 256; ++i)
buffer[i] = 0;
uint16_t packetSize;
ExampleMsg msg = {};
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
msg.name.funcs.encode = &encode_string;
msg.value = 17;
msg.number = 18;
char name[] = "Woo hoo!";
strncpy(msg.name, name, strlen(name));
pb_encode(&stream, ExampleMsg_fields, &msg);
packetSize = stream.bytes_written;
memcpy(packet, buffer, sizeof(buffer));
return packetSize;
}
Updated proto file:
syntax = "proto2"
import "nanopb.proto";
message ExampleMsg {
required int32 value = 1;
required int32 number = 2;
required string name = 3 [(nanopb).max_size = 40];
}
You can avoid callbacks by giving a maximum size for the string field using the option (nanopb).max_size = 123 in the .proto file. Then nanopb can generate a simple char array in the structure (relevant part of documentation).
Regarding why callbacks don't work: just a guess, but try adding extern "C" also to the callback function. I assume you are using C++ there, so perhaps on that platform the C and C++ calling conventions differ and that causes the crash.
Does the VxWorks serial console give any more information about the crash? I don't remember if it does that for functions called from LabView, so running some test code directly from the VxWorks shell may be worth a try also.
Perhaps the first hurdle is how the code handles strings.
LabVIEW's native string representation is not null-terminated like C, but you can configure LabVIEW to use a different representation or update your code to handle LabVIEW's native format.
LabVIEW stores a string in a special format in which the first four bytes of the array of characters form a 32-bit signed integer that stores how many characters appear in the string. Thus, a string with n characters requires n + 4 bytes to store in memory.
LabVIEW Help: Using Arrays and Strings in the Call Library Function Node
http://zone.ni.com/reference/en-XX/help/371361L-01/lvexcodeconcepts/array_and_string_options/

Reading from a binary file to byte array in j2me

I use below method for reading a binary file :
public void readFile()
{
try
{
Reader in = new InputStreamReader( this.getClass().getResourceAsStream( this.fileName));
int count = (in.read() * 0xFF) + in.read();
int heights = in.read();
this.shapes = new int[count][];
for(int ii = 0;ii<count;ii++)
{
int gwidth = in.read();
int[] tempG = new int[gwidth * heights];
int len = (in.read() * 0xff) + in.read();
for(int jj = 0;jj<len;jj++)
{
tempG[top++] = in.read() * 0x1000000;
}
this.shapes[ii] = tempG;
}
in.close();
}catch(Exception e){}
}
It works perfectly in netbeans emulator and some devices,but in some devices and in kemulator it seems that in.read(), read a char (two byte), and it causes my app crashes on those device and emulator.
what is the best method for reading file in bytes?
Since you are always dealing with bytes, you should use an InputStream rather than an InputStreamReader.
Add the Javadoc says:
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset. The charset that it uses may be specified by name or may be given explicitly, or the platform's default charset may be accepted.
And the read() method reads a "character":
On the other hand, an InputStream represents an input stream of bytes:
public abstract int read() throws IOException
Reads the next byte of data from the input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned. This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
(And for kicks, here's a dated article about "buffered readers" in j2me)
Best example I could find directly from Nokia
public Image readFile(String path) {
try {
FileConnection fc = (FileConnection)Connector.open(path, Connector.READ);
if(!fc.exists()) {
System.out.println("File doesn't exist!");
}
else {
int size = (int)fc.fileSize();
InputStream is = fc.openInputStream();
byte bytes[] = new byte[size];
is.read(bytes, 0, size);
image = Image.createImage(bytes, 0, size);
}
} catch (IOException ioe) {
System.out.println("IOException: "+ioe.getMessage());
} catch (IllegalArgumentException iae) {
System.out.println("IllegalArgumentException: "+iae.getMessage());
}
return image;
}
http://www.developer.nokia.com/Community/Wiki/How_to_read_an_image_from_Gallery_in_Java_ME

Resources