Convert array<Byte>^ data to const byte* data - C++/CLR - clr

I am trying to call a function in C from C# though c ++
so basically C# -> C++ - >C
In C#, I have byte[] bytes - which reads the information from the file. I am passing the byte array and the size to C++ .
In C++ I get the byte array and the size but I am not able to convert to the specific data types.
void Image::OpenMemFile(array<Byte>^ data, unsigned int size)
{
Free();
m_dataStream = data;
Byte const* streamData = &data[0]; // this is where it throws error
// Should I use marshaling here ? What call should that ;be ?
hImage = ::OpenMemImage(streamData , size);
modified = false;
}
// this is the function I need to call
EXIVSIMPLE_API HIMAGE OpenMemImage(const BYTE *data, unsigned int size)
{
// code
imgWrap->image = Exiv2::ImageFactory::open(data, size);
}
the C function it needs to call is
Image::AutoPtr ImageFactory::open(const byte* data, long size)
{
/// code
}
I need to help in converting the byte array to const byte* . I realize I need to use Marshaling. Is there a specific function to marshal arrays in C++ ?
Any help is appreciated.
Thanks

pin_ptr<unsigned char> pin_buffer = &data[0];
unsigned char* pData = pin_buffer;

Related

Variable in AnsiStringT template

I currently use the conversion function which looks like this (C++ Builder):
UnicodeString OutputInCodePage(const int CodePage, std::string& InStr, const unsigned Offs)
{
switch (CodePage)
{
default:
case 0: return AnsiStringT<0> (InStr.substr(Offs).c_str()); // System default
case 037: return AnsiStringT<037> (InStr.substr(Offs).c_str()); // IBM037 IBM EBCDIC US-Canada
case 437: return AnsiStringT<437> (InStr.substr(Offs).c_str()); // IBM437 OEM United States
case 500: return AnsiStringT<500> (InStr.substr(Offs).c_str()); // IBM500 IBM EBCDIC International
// And many more following...
}
}
But I really want to avoid the use of huge switch/case - something like this:
UnicodeString OutputInCodePage(const int CodePage, std::string& InStr, const unsigned Offs)
{
return AnsiStringT<CodePage> (InStr.substr(Offs).c_str());
}
That doesn't work and gives me E2396 Template argument must be a constant expression error.
Is there a way to re-do the code so I can use std::string raw data conversion (into UnicodeString) based on CodePage parameter without a huge switch/case list?
There is indeed a much easier way to handle this - use the RawByteString type and the SetCodePage() function, eg:
UnicodeString OutputInCodePage(const int CodePage, const std::string &InStr, const unsigned Offs)
{
RawByteString out(InStr.c_str() + Offs);
SetCodePage(out, CodePage, false);
return out;
}
Alternatively, use the UnicodeFromLocaleChars() function:
UnicodeString OutputInCodePage(const int CodePage, const std::string &InStr, const unsigned Offs)
{
UnicodeString out;
const char *p_in = InStr.c_str() + Offs;
int in_len = InStr.length() - Offs;
int out_len = UnicodeFromLocaleChars(CodePage, 0, p_in, in_len, NULL, 0);
if (out_len > 0)
{
out.SetLength(out_len);
UnicodeFromLocaleChars(CodePage, 0, p_in, in_len, out.c_str(), out_len);
}
return out;
}

byte array in arduino library

ok so here is one for you maybe simple but i am not so sure.
i have the following code and it may be clear what i wish to do by looking at the code.
Arduino.ino
RF myRF; //Creation of RF class.
const int dataSize = 500;
byte storedData[dataSize];
//array is populated through program then the following is called
myRF.populate(storedData);
RF.CCP
const int dataSize = 500;
byte recivedData[dataSize];
void RF::populate(byte reciveddata){
recivedData = reciveddata;
}
RF.H
#include Arduino.h
#ifndef RF_H
#define RF_H
class RF {
public:
RF();
~RF();
void recive();
void send();
void print();
void sendnew(byte Storeddata);
};
#endif
this is however producing an error "byte is not declared"
Hope its clear what i intend to do and hope you can help thanks.
There are two problems in your files:
h file:
#include Arduino.h
You should write
#include <Arduino.h>
c file:
const int dataSize = 500;
byte recivedData[dataSize];
void RF::populate(byte reciveddata){
recivedData = reciveddata;
}
Here you have a big problem. You are declaring recivedData here, but you want to assign it a value coming from another part of the program. This is not how it works.
IMO you have two ways to do this.
1) store just the pointer to the memory; this way is faster and occupies less memory than solution 2, but you have to ensure that the storedData variable you pass in the .ino file is not changed during the function
#include "RF.h" // I hope you already included this
byte *recivedData;
void RF::populate(byte *reciveddata){
recivedData = reciveddata;
}
2) copy the content of the received array to this array; this way you have a copy of the array, so you occupy twice the memory (but you can edit storedData without problems).
#include "RF.h" // I hope you already included this
const int dataSize = 500;
byte recivedData[dataSize];
int recivedDataLength;
void RF::populate(byte *reciveddata, int reciveddatalength){
recivedDataLength = (reciveddatalength>dataSize) ? dataSize : reciveddatalength;
for (int i = 0; i < recivedDataLength; i++)
recivedData[i] = reciveddata[i];
}

How to read in 8 bytes of data from a DataInputStream and interpreted it as double in Vala

I looking for the equivalent of
java.io.DataInputStream.readDouble() for Vala.
Is it even possible?
Currently I have :
public double data;
public override void load (DataInputStream dis) throws IOError {
data = dis.read_int64 ();
}
But it just converting a int64 to a double which is not what I want.
I've tried all sort of casting and de-referencing, but nothing seems to work.
This worked for me:
int main()
{
int64 foo = 0; // Whatever value you have
double data = *(double*)(&foo); // This is where the "magic" happens
stdout.printf("%f", data);
return 0;
}
Mind you, you may have to set the correct byte order for the conversion to succeed.

Parameters to use in a Vapi definition for passing arrays by reference

I have the following C code that uses libmodbus to read a single device register using ModbusTCP:
modbus_t *ctx;
uint16_t tab_reg[16];
ctx = modbus_new_tcp("10.0.1.77", 502);
modbus_read_registers(ctx, 0x20, 2, tab_reg);
printf("reg = %d (0x%X)\n", tab_reg[0], tab_reg[0]);
printf("reg = %d (0x%X)\n", tab_reg[1], tab_reg[1]);
now trying to switch this over to Vala using a Vapi that I've generated, the contents of that for new and read are:
[CCode (cheader_filename = "modbus.h", cname = "modbus_new_tcp")]
public static unowned Modbus.modbus_t create_tcp (string ip_address, int port);
public static int read_registers (Modbus.modbus_t ctx, int addr, int nb, uint16 dest);
[CCode (cheader_filename = "modbus.h")]
and the translated Vala program is:
class ModbusReadTest : GLib.Object {
unowned Modbus.modbus_t ctx;
public void run () {
uint16 reg = 0x00;
ctx = create_tcp ("10.0.1.77", 502);
Modbus.read_registers (ctx, 0x20, 2, reg);
message ("reg = %d (0x%X)", reg, reg);
Modbus.close(ctx);
}
}
Coincidentally, when I compile this into C code and then into a binary using gcc I get the error:
read-registers-test.c:71:2: warning: passing argument 4 of ‘modbus_read_registers’ makes pointer from integer without a cast [enabled by default]
which is not surprising. But I'm not sure how I should go about modifying the Vapi contents to closer match the prototype in the libmodbus header:
int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
I've tried a mix of array options and using 'out', but haven't been able to get more than a single double byte register at a time.
read_registers should probably be an instance method (on Modbus.modbus_t) instead of a static method, and Modbus.modbus_t should probably be renamed to something like Modbus.Context, create_tcp should probably be a constructor, and Modbus.close should be a free function on the Modbus.Context compact class, but that's beside the point of this question (if you stop by #vala on irc.gnome.org you can get help with that stuff).
You probably want to make it an array:
public static int read_registers (Modbus.modbus_t ctx, int addr, [CCode (array_length_pos = 2.5)] uint16[] dest);
Then you would do something like this in Vala:
public void run () {
uint16 reg[2];
ctx = create_tcp ("10.0.1.77", 502);
Modbus.read_registers (ctx, 0x20, reg);
message ("reg = %d (0x%X)", reg, reg);
Modbus.close(ctx);
}
For a port more faithful to the original C (where tab_reg has 16 elements instead of 2), you could use array slicing:
public void run () {
uint16 reg[16];
ctx = create_tcp ("10.0.1.77", 502);
Modbus.read_registers (ctx, 0x20, reg[0:2]);
stdout.printf ("reg = %d (0x%X)\n", reg, reg);
Modbus.close(ctx);
}
Note that if you make it an instance method you'll need to change the array_length_pos to 1.5.

How to pass ByteArray to C code using FlasCC

I want to pass ByteArray from ActionScript to C function.
basically I want do something like this:
void init() __attribute__((used,annotate("as3sig:public function init(byteData: ByteArray):int"),
annotate("as3package:example")));
void init()
{
//here I want to pass byteArray data to C variable.
//similar to AS3_GetScalarFromVar(cVar, asVar)
}
Unforunately I cannot find any function in flascc docs to help me with this.
Example:
void _init_c(void) __attribute((used,
annotate("as3sig:public function init(byteData:ByteArray) : void"),
annotate("as3import:flash.utils.ByteArray")));
void _init_c()
{
char *byteArray_c;
unsigned int len;
inline_as3("%0 = byteData.bytesAvailable;" : "=r"(len));
byteArray_c = (char *)malloc(len);
inline_as3("CModule.ram.position = %0;" : : "r"(byteArray_c));
inline_as3("byteData.readBytes(CModule.ram);");
// Now byteArray_c points to a copy of the data from byteData.
// Note that byteData.position has changed to the end of the stream.
// ... do stuff ...
free(byteArray_c);
}
The key here is that the heap in C is exposed on the AS3 side as CModule.ram, which is a ByteArray object.
A pointer malloc'd in C is seen in AS3 as an offset into CModule.ram.
You should use CModule.malloc and CModule.writeBytes methods to manipulate with pointers in C-style manner. Take a look on $FLASCC/samples/06_SWIG/PassingData/PassData.as
void _init_c(void) __attribute((used,
annotate("as3sig:public function init(byteData:ByteArray) : void"),
annotate("as3import:flash.utils.ByteArray")));
void _init_c()
{
char *byteArray_c;
unsigned int len;
inline_as3("%0 = byteData.bytesAvailable;" : "=r"(len));
byteArray_c = (char *) malloc(len);
inline_as3("byteData.readBytes(CModule.ram, %0, %1);" : : "r"(byteArray_c), "r"(len));
// Now byteArray_c points to a copy of the data from byteData.
// Note that byteData.position has changed to the end of the stream.
// ... do stuff ...
free(byteArray_c);
}

Resources