Pass structure via Microsoft RPC - visual-studio-2010

I got error while I was tying to pass structure from RPC client to server. Client calls Output3 procedure.
Definition in IDL:
struct BarStruct
{
byte a;
int b;
byte c;
char* d;
char* ddd;
};
void Output3([in] handle_t hBinding, [in, out] struct BarStruct* b);
Generated in header:
struct BarStruct
{
byte a;
int b;
byte c;
char *d;
char *ddd;
} ;
void Output3(
/* [in] */ handle_t hBinding,
/* [out][in] */ struct BarStruct *b);
implementation in server side:
void Output3(handle_t hBinding, struct BarStruct * b)
{
std::cout << "a=" << b->a << std::endl;
}
Client side code:
BarStruct b;
b.a=10;
std::cout<<"Output3"<<std::endl ;
Output3(hBinding, &b);
What might be wrong?

Your structure contains pointer to something, in the specific case pointer to char. When you want to transfer this to another process you have to keep in mind that a pointer is just and address value. When you want to pass the data where the pointer points to you need something different like a conformant array.
The basic idea is that you have to pass the length of the array that is address by the pointer.

Related

What is "WriteCallback" in C++ for Arduino?

In a library I use, there is a WriteCallback type. I don't know what is it, I cannot find it define anywhere ?
Could someone explain me what is WriteCallback ? Is it a native function or type in c++ ?
.h file
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WConstants.h"
#endif
typedef void (*WriteCallback) (const byte what); // send a byte to serial port
typedef int (*AvailableCallback) (); // return number of bytes available
typedef int (*ReadCallback) (); // read a byte from serial port
void sendMsg (WriteCallback fSend,
const byte * data, const byte length);
byte recvMsg (AvailableCallback fAvailable, ReadCallback fRead,
byte * data, const byte length,
unsigned long timeout = 500);
typedef void (*WriteCallback) (const byte what); defines a function pointer type which takes a const byte and returns a void. It is used to easily use function pointers. Just as uint8_t is defined using a typedef as: typedef unsigned char uint8_t; to be used as a easy shorthand for a 8bit width variable.
A example usage would be:
typedef void (*WriteCallback) (const byte what);
void sendMsg (WriteCallback fSend, const byte * data, const byte length);
void callbackfunction(const byte what) { /*do stuff*/ }
With a function call:
sendMsg(&callbackfunction,0);
Internally the sendMsg would call the function pointed to by the fSend variable which in this case is callbackfunction.
The usage of this typedef makes it possbile to easily define pointers to functions and as per example switch the used write callback.
Writecallback funcPtr;
void switchCallback(){
static int tmp = 0;
if(tmp)
funcPtr = &writecallbackA;
else
funcPtr = &writecallbackB;
tmp = (tmp) ? 0 : 1;
}
The above usage is more easily readable and comprehendeable than:
void (*fun_ptr) (const byte what);

Smart pointer operator[] "no match" when type is array with known length

Given the below code:
typedef std::unique_ptr<uint8_t[SHA256::DIGEST_SIZE]> sha256hash;
std::ostream& operator<<(std::ostream& os, const sha256hash &hash) {
// Save old formatting
std::ios oldFormat(nullptr);
oldFormat.copyfmt(os);
// Set up formatting
os << std::setfill('0') << std::setw(2) << std::hex;
// Do our printing
for (int i = 0;i < SHA256::DIGEST_SIZE; i++)
os << hash[i];
// Restore formatting
os.copyfmt(oldFormat);
}
I get the following error:
In function ‘std::ostream& operator<<(std::ostream&, const sha256hash&)’:
error: no match for ‘operator[]’ (operand types are ‘const sha256hash {aka const std::unique_ptr<unsigned char [32]>}’ and ‘int’)
os << hash[i];
I thought that the typedef would give me a smart pointer containing a pointer to an array of uint8_t and so operator[] should be indexing into that array. My best guesses at what's happening is that I'm instead saying that I want a unique_ptr to a pointer to an array of uint8_t. I think I see a couple of ways out of this but I'm not sure which is best
typedef std::unique_ptr<uint8_t[]> sha256hash;
compiles, but I'm not entirely sure that my overloaded operator won't try to print any unique_ptr to an array of ints.
I make a container struct for the int array, and put a unique_ptr around that.
Due to #PeterT's input I ended up going with my second option. A custom deleter seemed too far out of my way, and this was fairly easy to integrate into my already existing code. Here are my changes:
//! Light wrapper around SHA256 digest
class SHA256Hash {
//! The actual digest bits.
uint8_t buff[SHA256::DIGEST_SIZE];
public:
//! Pointer to a hash.
typedef std::unique_ptr<SHA256Hash> ptr;
//! Default constructor
SHA256Hash() : buff() { }
//! Operator to offer convenient buffer access
uint8_t &operator[](const uint8_t i) { return buff[i]; }
//! Operator to offer convenient buffer access
const uint8_t &operator[](const uint8_t i) const { return buff[i]; }
//! Offers access to the underlying digest
uint8_t *get() { return (uint8_t *) &buff; }
};
// Delegate to the version that prints references
std::ostream &operator<<(std::ostream &os, const SHA256Hash::ptr &hashp) {
os << *hashp;
return os;
}
std::ostream &operator<<(std::ostream &os, const SHA256Hash &hash) {
// Save old formatting
std::ios oldFormat(nullptr);
oldFormat.copyfmt(os);
// Set up formatting
os << std::setfill('0') << std::setw(2) << std::hex;
// Do our printing
for (int i = 0;i < SHA256::DIGEST_SIZE; i++)
os << (int) hash[i];
// Restore formatting
os.copyfmt(oldFormat);
return os;
}

copy_from_user is fetching unexpected data

I want to use the write sycall for copying a struct
from userspace to kernel.
In both user and kernel space, the struct is defined as
struct packet{
unsigned char packet[256];
int length;
}__attribute__ ((packed));
User space uses a local variable of type struct packet and passes it to the write syscall.
struct packet p;
/* ... (fill in data) */
printf("packet.length: %d\n",packet.length); /* looks correct */
result = write(uartFD, &p, sizeof(struct packet));
The kernel side looks like this, checking for correct length is done, just removed from example.
/* write syscall */
ssize_t packet_write(
struct file *file_ptr,
const char __user *user_buffer,
size_t count, loff_t *position)
{
struct packet p;
int retval;
if (copy_from_user((void*)&p, user_buffer, sizeof(struct packet))){
retval = -EACCES;
goto err;
}
/* looks wrong - different numbers like 96373062 or 96373958 */
printk("packet length: %d\n",p.length);
The opposite direction using read sycall is working as expected:
/* read syscall */
struct packet p;
/* ... (fill in data) */
copy_to_user(user_buffer, (void*)&p, sizeof(struct packet));
/* userspace */
read(uartFD, (void*)&packet, sizeof(struct packet));
What am I doing wrong with write syscall?
(Posted on behalf of the OP).
This is solved - it was my own silly. Both copying an integer and an unsigned char buffer separately was working, so it had to be something about the struct.
One site was packed, the other was not... reusing old code...

exposing a function with 2D slice as a parameter in a c-shared library (to be used in Java via JNA and C)

I am trying to write a simple matrix operations API using go and expose the APIs as a shared library. This shared library will be used from Java(using JNA) and from C.
The documentation is very sparse about using any data type beyond simple int or string as function parameters.
My requirement is to expose functions with 1 or more 2D slices as parameters AND also as return types. I am not able to figure out if such a thing is supported.
Is this possible? Are there any examples for this?
I think the key point is to have a look to the c bindings of slice,string and int generated by go build tool. I not tried 2D slice, but it should no different to 1D slice with unsafe pointer converter, maybe just be one more time allocation and convertion.
I'm not sure it's the best way, but here's the example for 1D slice:
the go part:
import "C"
//export CFoo
func CFoo(content []byte) string{
var ret []byte
//blablabla to get ret
cbuf := unsafe.Pointer(C.malloc(C.size_t(len(ret))))
C.memcpy(cbuf, unsafe.Pointer(&ret[0]), C.size_t(len(ret)))
var finalString string
hdr := (*reflect.StringHeader)(unsafe.Pointer(&finalString))
hdr.Data = uintptr(unsafe.Pointer(cbuf))
hdr.Len = len(ret)
return finalString
}
compile with -buildmode=c-shared, to get libmygo.so.
I not know JNA, expecting it like JNI. the JNI part as well as pure C part:
#include <stdio.h>
#include <jni.h>
#include <string.h>
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt32 GoInt;
typedef GoUint32 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
JNIEXPORT JNICALL jbyteArray Java_com_mynextev_infotainment_app_myev_Native_foo(JNIEnv* env, jobject obj,jbyteArray content){
JNIEnv ienv = *env;
void * Ccontent = ienv->GetByteArrayElements(env, content, 0);
int Lcontent = ienv->GetArrayLength(env, content);
GoSlice Gcontent = {Ccontent, Lcontent, Lcontent};
if(!gret.n){
printf("jni CDoAESEnc");
return NULL;
}
jbyteArray ret = ienv->NewByteArray(env, gret.n);
ienv->SetByteArrayRegion(env, ret, 0, gret.n, gret.p);
free((void*)gret.p);
ienv->ReleaseByteArrayElements(env, content, Ccontent, JNI_ABORT);
return ret;
}
build it with libmygo.so.
finally you get two so files. one for C which can be used standalone; one for Java which must be used with libmygo.so together.

Convert IDL structure with conformant array to header

I need to pass via Microsoft RPC structure with conformant array. This is how I write it in IDL:
struct BarStruct
{
byte a;
int b;
byte c;
long lArraySize;
[size_is(lArraySize)] char achArray[*];
};
Generated header:
struct BarStruct
{
byte a;
int b;
byte c;
long lArraySize;
char achArray[ 1 ];
} ;
Why achArray is fixed length of 1? How to pass array with for example 10 elements to it?
Something like this:
BarStruct* p = (BarStruct*)CoTaskMemAlloc(
offsetof(BarStruct, achArray) + 10*sizeof(char));
Basically, you need to allocate memory as if the structure had achArray[10] member at the end. offsetof(BarStruct, achArray) gives you the size of the fixed part of the structure, up to but not including achArray. To this, you add variable size of the array.

Resources