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.
Related
I was looking at Microsoft site about single inheritance. In the example given (code is copied at the end), I am not sure how memory is allocated to Name. Memory is allocated for 10 objects. But Name is a pointer member of the class. I guess I can assign constant string something like
DocLib[i]->Name = "Hello";
But we cannot change this string. In such situation, do I need allocate memory to even Name using new operator in the same for loop something like
DocLib[i]->Name = new char[50];
The code from Microsoft site is here:
// deriv_SingleInheritance4.cpp
// compile with: /W3
struct Document {
char *Name;
void PrintNameOf() {}
};
class PaperbackBook : public Document {};
int main() {
Document * DocLib[10]; // Library of ten documents.
for (int i = 0 ; i < 10 ; i++)
DocLib[i] = new Document;
}
Yes in short. Name is just a pointer to a char (or char array). The structure instantiation does not allocate space for this char (or array). You have to allocate space, and make the pointer(Name) point to that space. In the following case
DocLib[i]->Name = "Hello";
the memory (for "Hello") is allocated in the read only data section of the executable(on load) and your pointer just points to this location. Thats why its not modifiable.
Alternatively you could use string objects instead of char pointers.
Is it possible to display value of module_param when read, in hex?
I have this code in my linux device driver:
module_param(num_in_hex, ulong, 0644)
$cat /sys/module/my_module/parameters/num_in_hex
1234512345
Would like to see that value in hex, instead of decimal. Or, should I use different way like debugfs for this?
There is no ready parameter type (2nd argument of module_param macro), which output its argument as hexadecimal. But it is not difficult to implement it.
Module parameters are driven by callback functions, which extract parameter's value from string and write parameter's value to string.
// Set hexadecimal parameter
int param_set_hex(const char *val, const struct kernel_param *kp)
{
return kstrtoul(val, 16, (unsigned long*)kp->arg);
}
// Read hexadecimal parameter
int param_get_hex(char *buffer, const struct kernel_param *kp)
{
return scnprintf(buffer, PAGE_SIZE, "%lx", *((unsigned long*)kp->arg));
}
// Combine operations together
const struct kernel_param_ops param_ops_hex = {
.set = param_set_hex,
.get = param_get_hex
};
/*
* Macro for check type of variable, passed to `module_param`.
* Just reuse already existed macro for `ulong` type.
*/
#define param_check_hex(name, p) param_check_ulong(name, p)
// Everything is ready for use `module_param` with new type.
module_param(num_in_hex, hex, 0644);
Check include/linux/moduleparam.h for implementation module_param macro and kernel/params.c for implementation of operations for ready-made types (macro STANDARD_PARAM_DEF).
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.
I am stuck trying to figure out how to initialize a pointer to a 3d array inside a 2d structure array. I had it working fine when I could declare the structure like this:
#define ROUSSEAU 300
#define OSSO 500
#define MOJO 9000
typedef struct x_primitive
{
short avg[ROUSSEAU][OSSO][MOJO];
} xprimitive;
But unfortunately the structure is too large to declare as a global. So I have to calloc the memory (192GB memory available on the system: win 7 64 bit);
typedef struct x_primitive
{
short ***avg;
} xprimitive;
xprimitive **xPmtv, *_xPmtv;
void xallocatePmtvMemory(void)
{
int structureCount = 10;
unsigned __int64 pmtvStructureSize = ROUSSEAU * OSSO * MOJO * sizeof(short);
unsigned __int64 memoryBlockSize = structureCount * pmtvStructureSize;
_xPmtv = (xprimitive *) calloc(structureCount, pmtvStructureSize);
xPmtv = (xprimitive **) calloc(structureCount, sizeof(xprimitive *));
for ( int i = 0; i < structureCount; ++i)
{
unsigned __int64 index = i * pmtvStructureSize;
xPmtv[i] = &_xPmtv[ index ];
// **************** here is the problem ******
xPmtv[i]->avg[ROUSSEAU][OSSO][MOJO] = &_xPmtv[ index + (ROUSSEAU + OSSO + MOJO) ];
}
}
I am trying to assign the "avg" variable to a chunk of memory, and utterly failing.
Pointers and arrays aren't interchangeable in the way you seem to be wanting them to be. I think you can probably be doing something much simpler. Make avg into a pointer:
typedef struct x_primitive
{
short (*avg)[ROUSSEAU][OSSO][MOJO];
} xprimitive;
And then allocate the space for the array at runtime:
xprimitive xPmtv;
xPmtv.avg = calloc(1, ROUSSEAU * OSSO * MOJO * sizeof(short));
Using it is a bit funny looking, though:
(*xPmtv.avg)[1][2][3]
If you have multiple structures, just throw the initialization into a loop. Maybe a better idea is to use a flexible array member to keep the usage syntax looking a bit more normal - it will cost you a dummy entry in the structure - flexible array members aren't allowed to play around on their own. Then again, why do you have a structure with only one field anyway?
typedef struct x_primitive
{
int dummyEntry;
short avg[][OSSO][MOJO];
} xprimitive;
To allocate one, you'd use:
xprimitive *xPmtv = calloc(1, sizeof(xprimitive) + ROUSSEAU * OSSO * MOJO * sizeof(short));
And access the array something like:
xPmtv->avg[1][2][3]
I am trying to send a user-defined structure named ABC using boost::mpi::send () call.
The given struct contains a vector "data" whose size is determined at runtime. Objects of struct ABC are sent by master to slaves.
But the slaves need to know the size of vector "data" so that the sufficient buffer is available on the slave to receive this data.
I can work around it by sending the size first and initialize sufficient buffer on the slave before receiving the objects of struct ABC. But that defeats the whole purpose of using STL containers.
Does anyone know of a better way to do handle this ? Any suggestions are greatly appreciated.
Here is a sample code that describes the intent of my program. This code fails at runtime due to above mentioned reason.
struct ABC
{
double cur_stock_price;
double strike_price;
double risk_free_rate;
double option_price;
std::vector <char> data;
};
namespace boost
{
namespace serialization
{
template<class Archive>
void serialize (Archive &ar,
struct ABC &abc,
unsigned int version)
{
ar & abc.cur_stock_price;
ar & abc.strike_price;
ar & abc.risk_free_rate;
ar & abc.option_price;
ar & bopr.data;
}
}
}
BOOST_IS_MPI_DATATYPE (ABC);
int main(int argc, char* argv[])
{
mpi::environment env (argc, argv);
mpi::communicator world;
if (world.rank () == 0)
{
ABC abc_obj;
abc.cur_stock_price = 1.0;
abc.strike_price = 5.0;
abc.risk_free_rate = 2.5;
abc.option_price = 3.0;
abc_obj.data.push_back ('a');
abc_obj.data.push_back ('b');
world.send ( 1, ANY_TAG, abc_obj;);
std::cout << "Rank 0 OK!" << std::endl;
}
else if (world.rank () == 1)
{
ABC abc_obj;
// Fails here because abc_obj is not big enough
world.recv (0,ANY_TAG, abc_obj;);
std::cout << "Rank 1 OK!" << std::endl;
for (int i = 0; i < abc_obj;.data.size(); i++)
std::cout << i << "=" << abc_obj.data[i] << std::endl;
}
MPI_Finalize();
return 0;
}
You shouldn't send the vector object itself in the message, as the receiver only needs its contents, and the internal state of the vector would probably be all messed up after receiving anyway (memory addresses that were valid on the sending end probably won't be valid on the receiving end).
Instead, here's what you need to do:
Define a separate struct with four doubles and a simple char array.
Whenever you need to send, create a temporary variable of this new struct, and fill the char array with the contents of the vector you want to send.
Define a temporary MPI datatype that matches the size of this specific struct object.
Send the temporary struct as an instance of this temporary datatype.
Receive it in a suitably large receive buffer (or send the size in advance)
Reconstruct the ABC struct based on the contents of the char array.
At least, that's what you need to do with vanilla C++ and MPI. I'm not familiar with boost, so I don't know if it makes any of these steps easier.
BOOST_IS_MPI_DATATYPE is only for fixed length data. Your array is not fixed length and this is why it fails.