By following this tutorial, I've tried to extend my HDF5 dataset. The code is the following, however the data is not properly written to the dataset (the dataset has the proper final size but contains only zeros). The only difference from the tutorial is that I have to use dynamic arrays. Any idea?
int main()
{
hsize_t dims[1], max_dims[1], newdims[1], chunk_dims[1], offset[1];
hid_t file, file_space, plist, dataset, mem_space;
int32_t *buffer1, *buffer2;
file = H5Fcreate("test.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
// Create dataspace with initial dim = 0 and final = UNLIMITED
dims[0] = 0;
max_dims[0] = H5S_UNLIMITED;
file_space = H5Screate_simple(RANK, dims, max_dims);
// Create dataset creation property list to have chunks
plist = H5Pcreate(H5P_DATASET_CREATE);
H5Pset_layout(plist, H5D_CHUNKED);
chunk_dims[0] = 2;
H5Pset_chunk(plist, RANK, chunk_dims);
// Create the dataset
dataset = H5Dcreate(file, "Test", H5T_NATIVE_INT32, file_space, H5P_DEFAULT, plist, H5P_DEFAULT);
H5Pclose(plist);
H5Sclose(file_space);
//## FIRST BUFFER
int length = 6;
buffer1 = new int32_t[length];
for (hsize_t i = 0; i < length; i++)
buffer1[i] = i;
// Extend the dataset by getting previous size and adding current length
file_space = H5Dget_space(dataset);
H5Sget_simple_extent_dims(file_space, dims, NULL);
newdims[0] = dims[0] + length;
H5Dset_extent(dataset, newdims);
// Select hyperslab on the file dataset
offset[0] = dims[0];
dims[0] = length;
H5Sselect_hyperslab(file_space, H5S_SELECT_SET, offset, NULL, dims, NULL);
// Dataspace for buffer in memory
mem_space = H5Screate_simple(RANK, dims, NULL);
// Append buffer to dataset
H5Dwrite(dataset, H5T_NATIVE_INT32, mem_space, file_space, H5P_DEFAULT, buffer1);
H5Sclose(file_space);
H5Sclose(mem_space);
//## SECOND BUFFER
length = 4;
buffer2 = new int32_t[length];
for (hsize_t i = 0; i < length; i++)
buffer2[i] = i;
// Extend the dataset by getting previous size and adding current length
file_space = H5Dget_space(dataset);
H5Sget_simple_extent_dims(file_space, dims, NULL);
newdims[0] = dims[0] + length;
H5Dset_extent(dataset, newdims);
// Select hyperslab on the file dataset
offset[0] = dims[0];
dims[0] = length;
H5Sselect_hyperslab(file_space, H5S_SELECT_SET, offset, NULL, dims, NULL);
// Dataspace for buffer in memory
mem_space = H5Screate_simple(RANK, dims, NULL);
// Append buffer to dataset
H5Dwrite(dataset, H5T_NATIVE_INT32, mem_space, file_space, H5P_DEFAULT, buffer2);
H5Sclose(file_space);
H5Sclose(mem_space);
H5Dclose(dataset);
H5Fclose(file);
delete[] buffer1;
delete[] buffer2;
}
I've figured out how to solve the problem. It has nothing to do with the dynamic arrays. The problem is that after calling H5Sget_simple_extent_dims the dataspace id gets somehow invalidated (I do not understand why...a bug?) and you need to get it again before reusing it, e.g. before selecting the hyperslab:
// Select hyperslab on the file dataset
offset[0] = dims[0];
dims[0] = length;
H5Dclose(file_space); // --ADDED-- CLOSE THE PREVIOUSLY OPENED
file_space = H5Dget_space(dataset); // --ADDED-- REOPEN
H5Sselect_hyperslab(file_space, H5S_SELECT_SET, offset, NULL, dims, NULL);
Related
I'm implementing an iterator to go over the records from a Berkeley DB. However, it seems I need to set the DB_DBT_USERMEM flag before the call to cursor->get with DB_NEXT.
Doing it that way would make my iterator less cohesive and will have to implement multiple iterators for each data type I want to retrieve.
Is there a way to have a generic iterator that can traverse structures w/o pointers, and basic data types? Here's what I'm trying to achieve.
#include <stdio.h>
#include <string.h>
#include <db.h>
// let this function handle integers and use DB_DBT_USERMEM for memory alignment
void integer_items(DBT key, DBT data) {
int number = 0;
data.data = &number;
data.flags = DB_DBT_USERMEM;
data.ulen = sizeof(int);
printf("key is: %s, data is: %d\n", (char *) key.data,number);
}
// let this function handle pointer structs. No need for DB_DBT_USERMEM
void ptr_struct_items(DBT key, DBT data) {
// MY_STRUCT user;
// marshall struct...
// buffsize = sizeof(int) +(strlen(user.familiar_name) + strlen(user.surname) + 2);
// databuff = malloc(buffsize);
// memset(databuff, 0, buffsize);
// ...
// printf("key is: %s, data is: %d\n", (char *) key.data,number);
}
int iterator(DB *database, void(*function)(DBT key, DBT data)) {
DBT key, data;
DBC *cursor;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
database->cursor(database, NULL, &cursor, 0);
while(cursor->c_get(cursor, &key, &data, DB_NEXT) == 0){
(*function)(key, data);
}
cursor->c_close(cursor);
return 0;
}
int main() {
DB_ENV *myEnv;
DB *dbp;
DBT key, data;
int r, v = 10;
char *k = "Test";
db_env_create(&myEnv, 0);
myEnv->open(myEnv, "./", DB_CREATE | DB_INIT_MPOOL, 0);
db_create(&dbp, myEnv, 0);
dbp->open(dbp, NULL, "test.db", NULL, DB_HASH, DB_CREATE, 0664);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = k;
key.size = strlen(k) +1;
data.data = &v;
data.size = sizeof(int);
if((r=dbp->put(dbp, NULL, &key, &data, 0)!=0))
fprintf(stderr, "%s\n", db_strerror(r));
iterator(dbp, integer_items);
iterator(dbp, ptr_struct_items);
return 0;
}
You almost always want to use DB_DBT_USERMEM, if only to avoiding the malloc() from inside BDB for DB_DBT_MALLOC/REALLOC. When you use it, you must pass in your own memory large enough to hold the largest item in your database. This holds for the key DBT too, as you may want to use it there.
In your example, as the key and data are so small, I'd just put character arrays on the stack in your "iterator" function, and then initialize key and data after the call to memset(). What you've got above is wrong because you're setting USERMEM after the call to c_get().
Here's a reworked example that gives BDB 256 bytes to work with for key and data.
void integer_items(DBT key, DBT data) {
int number = 0;
if (data.size == sizeof number) {
number = *(int *)data.data;
printf("key is: %s, data is: %d\n", (char *) key.data, number);
}
}
int iterator(DB *database, void(*function)(DBT key, DBT data)) {
DBT key, data;
DBC *cursor;
char kmem[256];
char dmem[256];
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.flags = DB_DBT_USERMEM;
key.data = kmem;
key.ulen = sizeof kmem;
data.flags = DB_DBT_USERMEM;
data.data = dmem;
data.ulen = sizeof dmem;
database->cursor(database, NULL, &cursor, 0);
while(cursor->c_get(cursor, &key, &data, DB_NEXT) == 0){
(*function)(key, data);
}
cursor->c_close(cursor);
return 0;
}
To handle different structures inside your iterator, include the data type as part of the key somehow. For example, instead of a bare integer for the key, use a struct, and have the first character define which kind of type it is. Then, inside your iterator function, you can switch on that.
i have an this input file .txt where there are sequences:
NAMEOFSEQUENCE1/SEQUENCE1
NAMEOFSEQUENCE2/SEQUENCE2
NAMEOFSEQUENCE3/SEQUENCE3
I done a struct:
typedef struct lane{
char *name;
char *sequence;
}lane;
and wrote this code:
int i=0;
lane* toSend = malloc(sizeof(*toSend)*3);
while (fgets(line,strlen(line),fileinput) != NULL){
//GETTING NAME AND SEQUENCE, LINE PER LINE
char *tempName = malloc(strlen(line)-strlen(strstr(line,"\\"))+1);
strncpy(tempName,line,strlen(line)-strlen(strstr(line,"\\")));
tempName[strlen(line)-strlen(strstr(line,"\\"))] = '\0';
char *tempSequence = malloc(strlen(strstr(line,"\\")));
strncpy(tempSequence,strstr(line,"\\")+1,strlen(strstr(line,"\\")));
tempSequence[strlen(strstr(line,"\\"))-1] = '\0';
//FILLING TOSEND
toSend[i].name = malloc(strlen(line)-strlen(strstr(line,"\\"))+1);
toSend[i].sequence = malloc(strlen(strstr(line,"\\")));
howmuchbyte += strlen(line)+1;
strcpy(toSend[i].name,tempName);
strcpy(toSend[i].sequence,tempSequence);
i++;
}
I put in "line" variable one line of the file at a time and put in tempName the NAMEOFSEQUENCEX of each sequence and put in tempSequence the SEQUENCEX.
At this point all is working. If i Print the "toSend" vector i get the right value!
So i wrote this:
MPI_Send(toSend, 3, MPI_BYTE, 1, tag, MPI_COMM_WORLD);
so i send from process with rank 0 to process with rank 1 (i have 2 process). I put 3 as count parameter because i have 3 elements in the array.
The process with rank 1 do this:
lane* received = malloc(sizeof(*received)*3);
MPI_Recv(received, 3, MPI_BYTE, 0, tag, MPI_COMM_WORLD, &status);
If i do this on process with rank 1:
printf("%s",received[0].name);
i get a segmentation fault. What do i wrong?
This could work if your strings are of fixed maximum length, e.g.
typedef struct lane{
char name[NAME_MAX];
char sequence[SEQ_MAX];
}lane;
In that case you can simply define a new MPI structured datatype and use it in both send and receive operations:
int blens[2] = { NAME_MAX, SEQ_MAX };
int disps[2] = { offsetof(lane, name), offsetof(lane, sequence) };
int oldtypes[2] = { MPI_CHAR, MPI_CHAR };
MPI_Datatype type_lane;
MPI_Type_create_struct(2, blens, disps, oldtypes, &type_lane);
MPI_Type_commit(&type_lane);
lane aLane[2];
if (rank == 0)
{
strncpy(aLane[0].name, NAME_MAX, "foo1");
strncpy(aLane[0].sequence, SEQ_MAX, "bar");
strncpy(aLane[1].name, NAME_MAX, "foo2");
strncpy(aLane[1].sequence, SEQ_MAX, "baz");
MPI_Send(aLane, 2, type_lane, 1, tag, MPI_COMM_WORLD);
}
else if (rank == 1)
{
MPI_Recv(aLane, 2, type_lane, 0, tag, MPI_COMM_WORLD, &status);
}
If your strings are of strongly varying lengths, then you should serialize each structure before sending it. The most simple thing that comes to my mind is to just concatenate all name/sequence pairs, separated by a NUL:
int total_length = 0;
for (i = 0; i < num_to_send; i++)
total_length += strlen(toSend[i].name) + strlen(toSend[i].sequence) + 2;
char *bigstr = malloc(total_length);
char *cur = bigstr;
for (i = 0; i < num_to_send; i++)
{
strcpy(cur, toSend[i].name);
cur += strlen(toSend[i].name) + 1;
strcpy(cur, toSend[i].sequence);
cur += strlen(toSend[i].sequence) + 1;
}
Now the content of bigstr is as follows:
toSend[0].name \0 toSend[0].sequence \0 toSend[1].name \0 toSend[1].sequence \0 ....
The sender can now send the string and dispose it:
MPI_Send(bigstr, total_length, MPI_CHAR, 1, tag, MPI_COMM_WORLD);
The receiver has to be prepared to receive a message of unknown size. That can be achieved by first calling MPI_Probe and then MPI_Recv:
MPI_Status;
MPI_Probe(1, tag, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_CHAR, &total_length);
char *bigstr = malloc(total_length);
MPI_Recv(bigstr, total_length, MPI_CHAR, 1, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
Now comes the part where you have to deserialise the big string into a collection of tuples. One way to do it is to first walk it and count the number of NULs and divide them by two. Then walk it again and copy each item to the corresponding location:
int num_structs = 0;
for (i = 0; i < total_length; i++)
if (bigstr[i] == '\0') num_structs++;
num_structs /= 2;
lane *lanes = malloc(num_structs * sizeof(lane));
char *cur = bigstr;
for (i = 0; i < num_structs; i++)
{
lanes[i].name = strdup(cur);
cur += strlen(cur);
lanes[i].sequence = strdup(cur);
cur += strlen(cur);
}
Another possible solution would be to utilise MPI_Pack and MPI_Unpack instead.
You can't just send raw pointers across an MPI channel. Well, you can, but the process that receives a pointer from some other process won't have the same data at the memory location (in their own memory space) referred to by the pointer.
If you want to send a variably-sized array (such as a string) through MPI, you'll need to test for the size of the array first, and allocate an appropriately sized array on the receiving end.
For more info: How to send and receive string using MPI
I am new to C but I am currently working on a C program which I am having an issue with relating to structures and memory allocation.
What I have in my code is a permanent while loop which will break out of when a certain condition is met. Within this while loop it checks the database and has a while loop to loop round the MySQL rows.
When the program first loads, it creates 3 structures, one of the structures also containing a linked list and initialised to be a size of 100.
As my program loops through the MySQL rows it checks whether 100 records have been added, and if so, then does a realloc to increase the size by another 100 rows. When I have looped through all of the MySQL rows it then returns to main while loop (the never ending loop) and NULL's the structures and then initialises them again to be 100 rows and starts all over again.
The problem I am having, is once it does the first complete loop through all of the mysql rows and returns to the main never ending loop and the structures are reinitialised back to be a size of 100, on the 17th row my program segfaults. When I inspect everything in GDB the structure at index 17 comes up saying that the certain elements within the structure are out of bounds.
Below is the definition for the structure I am having the issue with.
typedef struct CallLogSearchDataStruct
{
char * date;
char * time;
char * bParty;
char * aParty;
float duration;
char * cleardownCause;
struct CallLogSearchOutboundStruct * outboundLegs;
} callLogSearchDataStruct;
Below is how the structure initially get set up when the program first runs
callLogSearchData = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchDataStruct));
callLogSearch = calloc(INITIAL_CALL_STRUCT_SIZE,sizeof(callLogSearchResultStruct));
switches = calloc(INITIAL_CALL_STRUCT_SIZE, sizeof(switchIDStructure));
INITIAL_CALL_STRUCT_SIZE is equal to 100.
Below is the code for how the reallocateStructures function is called. This reallocates the structures by adding another 100 in size to the original size.
if (reallocateStructures(&callLogSearch, &callLogSearchData, &switches, ×StructHasBeenReallocated, currentStructIndexValue, dataRow) == 0)
{
//Structures have been reallocated so reset the index
currentStructIndexValue = 0;
}
Below is the actual code for the reallocating of the structures
int reallocateStructures(callLogSearchResultStruct **callLogSearch, callLogSearchDataStruct ** callLogSearchData,
switchIDStructure ** switches, int *timesStructHasBeenReallocated, int currentStructIndexValue,
int dataRow)
{
int INITIAL_CALL_STRUCT_SIZE = 100;
int currentSize = 0;
int newSize = 0;
int initFromIndex = 0;
callLogSearchResultStruct * callLogSearchTemp;
callLogSearchDataStruct * callLogSearchDataTemp;
switchIDStructure * switchesTemp;
printf("Current Struct Index Value: %i\n", currentStructIndexValue);
if (currentStructIndexValue >= INITIAL_CALL_STRUCT_SIZE) {
printf("REALLOCATING STRUCTURES");
currentSize = currentStructIndexValue * *timesStructHasBeenReallocated;
newSize = currentSize + INITIAL_CALL_STRUCT_SIZE;
*timesStructHasBeenReallocated = *timesStructHasBeenReallocated + 1;
callLogSearchTemp= (callLogSearchResultStruct*)realloc(*callLogSearch, (newSize * sizeof(callLogSearchResultStruct)));
callLogSearchDataTemp = (callLogSearchDataStruct*)realloc(*callLogSearchData, (newSize * sizeof(callLogSearchDataStruct)));
switchesTemp = (switchIDStructure*)realloc(*switches, (newSize * sizeof(switchIDStructure)));
/**callLogSearchData = realloc(*callLogSearchData, newSize * sizeof (callLogSearchDataStruct));
*callLogSearch = realloc(*callLogSearch, newSize * sizeof (callLogSearchResultStruct));
*switches = realloc(*switches, newSize * sizeof (switchIDStructure));
*/
for (initFromIndex = currentSize; initFromIndex < newSize; initFromIndex++) {
callLogSearchDataTemp[initFromIndex].aParty = NULL;
callLogSearchDataTemp[initFromIndex].bParty = NULL;
callLogSearchDataTemp[initFromIndex].cleardownCause = NULL;
callLogSearchDataTemp[initFromIndex].date = NULL;
callLogSearchDataTemp[initFromIndex].duration = 0;
callLogSearchDataTemp[initFromIndex].outboundLegs = NULL;
callLogSearchDataTemp[initFromIndex].time = NULL;
callLogSearchTemp[initFromIndex].date = NULL;
callLogSearchTemp[initFromIndex].dRowIndex = dataRow;
switchesTemp[initFromIndex].switchID = NULL;
if (initFromIndex == newSize - 1)
{
printf("debugging here\n");
}
}
*callLogSearch = callLogSearchTemp;
*callLogSearchData = callLogSearchDataTemp;
*switches = switchesTemp;
return 0;
}
else
{
return 1;
}
}
Below is the code where after it has looped through all of the MySQL rows the structures are then reset and re-initialised to be a size of 100.
//Check if function has looped round already and if so reset all structures
if (dataRow > -1)
{
numberOfTimesEverythingHasReset++;
callLogSearchData = NULL;
callLogSearch = NULL;
switches = NULL;
callLogSearchData = realloc(callLogSearchData, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
callLogSearch = realloc(callLogSearch, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
switches = realloc(switches, INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//initialiseNewStructure(&callLogSearch, &callLogSearchData, &switches);
//callLogSearchData = (callLogSearchDataStruct*)realloc(callLogSearchData, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
//callLogSearch = (callLogSearchResultStruct*)realloc(callLogSearch, INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
//switches = (switchIDStructure*)realloc(switches, INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//Initialise all elements within structures
for (initFromIndex = INITIAL_CALL_STRUCT_SIZE; initFromIndex < INITIAL_CALL_STRUCT_SIZE; initFromIndex++)
{
callLogSearchData[initFromIndex].aParty = NULL;
callLogSearchData[initFromIndex].bParty = NULL;
callLogSearchData[initFromIndex].cleardownCause = NULL;
callLogSearchData[initFromIndex].date = NULL;
callLogSearchData[initFromIndex].duration = 0;
callLogSearchData[initFromIndex].outboundLegs = NULL;
callLogSearchData[initFromIndex].time = NULL;
callLogSearch[initFromIndex].date = NULL;
callLogSearch[initFromIndex].dRowIndex = dataRow;
}
timesStructHasBeenReallocated = 1;
currentSize = 0;
}
currentStructIndexValue = 0;
I'm not sure why when it enters the if statement the first time to reset the structures back to a size of 100, after the 17 MySQL row the memory is then out of bounds so I segfault.
Thanks for any help you can provide.
UPDATE
I have fixed the issue with the for loop as per #Rohan answer but I am now getting a slightly different issue.
I am now getting a different area when trying to add data to the structures but I am not sure if the structures are anything to do with it as it seems to be the MySQL array having an out of bounds issue now causing a seg fault.
The line where it is failing is
callLogSearchData[dataRow].bParty = strdup(rowReport[bPartyColIndex]);
When I inspect rowReport in GDB it seems to have garbage inside it and at the 7th index (bPartyColIndex is at index 9) I start to see the out bounds error.
rowReport is assigned at each time the loop for each mysql row as shown in the code below
sqlLen = asprintf(&sql, "SELECT Tmp.SwitchID, Tmp.CorrelationID, SeizeUTC as Date, "
"SeizeUTC as Time, Direction, ACMToAns/100 as ACMToAns, Duration/100 as Duration, "
"CleardownCause, AParty, Tmp.BParty FROM TMP_Log AS Tmp ORDER BY SeizeUTC, "
"Tmp.SwitchID, Tmp.CorrelationID, Direction, SeizeCSec LIMIT %i, %i",
index, count);
SL_DebugAll(DBG_INFO, sql);
if ((mysql_real_query(HandleDB, sql, sqlLen))) return 1;
resultReport = mysql_store_result(HandleDB);
if (mysql_num_rows(resultReport) == 0 || index > atoi(limit))
{
SL_DebugAll(DBG_INFO, "Data retrieval for call log complete");
break;
}
else
{
numRows = mysql_num_rows(resultReport);
swID = -1;
corrID = -1;
dataRow = -1;
if (numRows > 0)
{
maxTargets = 1;
}
audioRow = mysql_fetch_row(audioResult);
sspSwitchID = atoi(audioRow[switchIDColIndex]);
sspCorrID = atoi(audioRow[correlationIDColIndex]);
inbound_counter = 0;
while (rowReport = mysql_fetch_row(resultReport))
In last code section of yours you have
if (dataRow > -1)
{
numberOfTimesEverythingHasReset++;
callLogSearchData = NULL;
callLogSearch = NULL;
switches = NULL;
callLogSearchData = realloc(callLogSearchData,
INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchDataStruct));
callLogSearch = realloc(callLogSearch,
INITIAL_CALL_STRUCT_SIZE*sizeof(callLogSearchResultStruct));
switches = realloc(switches,
INITIAL_CALL_STRUCT_SIZE*sizeof(switchIDStructure));
//Initialise all elements within structures
for (initFromIndex = INITIAL_CALL_STRUCT_SIZE;
initFromIndex < INITIAL_CALL_STRUCT_SIZE;
initFromIndex++)
{
....
You are setting callLogSearchData to NULL so reallocating is not relevant.
And you are allocating for INITIAL_CALL_STRUCT_SIZE number of elements, but your for loop counter starts from INITIAL_CALL_STRUCT_SIZE so effectively for loop does not execute.
I've managed to find out what the issue, its a pretty basic mistake unfortunately.
Because of where the code was crashing, I thought it had to be something related to the way I was re-initialised the structure, maybe because of the way I was using pointers.
However, this was not the case instead, instead, somewhere else in the code I was adding some data to one of the structures using an index called fileRow. Each time a value was added to the structure I incremented fileRow however I forgot to reset back to 0 when I realloced the structures, so when I realloced the structures to be of size 100, I was inserting into the structure of where fileRow was which was set to 1300 so each time I looped round I smashed up the memory until it segfaulted.
Thanks for your help and suggestions.
pointers always get me in C programing.
I am having trouble, I want to pass a pointer to an array of structs into a function so it can modify the structs and then pass the members of the array can be used in other functions later. The problem is when I think I index the array and point it to the modified struct then I try to look at the members later they aren't the modified values. Here is some of my code
typedef struct
{
int rows;
int columns;
int *data;
} Mat;
int main(void)
{
Mat result, decoded_result;
int result_data[8] =
{ 0, 0, 0, 0, 0, 0, 0, 0 };
int decoded_data[4] =
{ 0, 0, 0, 0 };
result.columns = 1;
result.rows = 8;
result.data = &result_data[0];
decoded_result.columns = 1;
decoded_result.rows = 4;
decoded_result.data = &decoded_data[0];
Mat m1, m2, m3, m4, m5;
m1.rows = m2.rows = m3.rows = m4.rows = m5.rows = 4;
m1.columns = m2.columns = m3.columns = m4.columns = m5.columns = 1;
int md1[4], md2[4], md3[4], md4[4], md5[4];
m1.data = &md1[0], m2.data = &md2[0], m3.data = &md3[0], m4.data = &md4[0], m5.data =
&md5[0];
Mat mat_array[10] =
{ m1, m2, m3, m4, m5 };
decode_data(&result, &decoded_result, mat_array);
return 0;
}
int decode_data(Mat *result, Mat *decoded_result, Mat *mat_array)
{
int ii;
int size_of_EEPROM = 5;
//steps to decode data
for (ii = 0; ii < size_of_EEPROM; ii++)
{
decode(result, decoded_result); //decodes hamming 8,4, works
mat_array[ii] = *decoded_result; ///This is where the problem is
}
return 0;
}
Thanks in advance for the help with pointers :)
As Mat carries a pointer, simply assigning Mat a to Mat b won't work. At least not for the data referenced by Mat's member data.
What's needed to be done here is also called a Deep Copy. Deep coping would also create a copy of what is referenced by data.
Below is an example of how this could be done for Mat.
Note: As negative rows and columns are of no use you'd better declare Mat like this:
typedef struct
{
size_t rows;
size_t columns;
int * data;
} Mat;
(As size_t is defined to be unsigned this kind of declaration makes it unnecessary to test for negative values carried by the members rows and columns before allocating the new data when deep-coping as shown below)
#include <stdlib.h> /* for malloc(), size_t */
#include <string.h> /* for memcpy() */
#include <errno.h> /* for errno, ENOMEM, EINVAL */
...
/* Deep-copies src to dst. */
/* Returns 0 on success or -1 on error. Sets errno in the latter case. */
int mat_copy(Mat * dst, const Mat * src)
{
if ((!dst) || (!src))
{
errno = EINVAL;
return -1;
}
dst->rows = src->row;
dst->columns = src->columns
dst->data = NULL;
if (src->data)
{
size_t size = dst->rows * dst->columns * sizeof (*(dst->data));
dst->data = malloc(size);
if (!dst->data)
{
errno = ENOMEM;
return -1;
}
memcpy(dst->data, src->data, size);
}
return 0;
}
There is rule of three in C++ when using pointers. It says that if you need one of following then you need other two always. These three are Destructor/Copy Constructor/Assign Operator.
So what happen's in your scenario. When you write mat_array[ii] = *decoded_result it actually makes:
mat_array[ii].rows = decoded_result.rows;
mat_array[ii].columns = decoded_result.columns;
mat_array[ii].data = decoded_result.data // here just assign pointers, not the entire data.
In this case you have to make assignment operator to make actual copy of data.
I am trying to get bitmap from mouse cursor, but with next code, i just can't get colors.
CURSORINFO cursorInfo = { 0 };
cursorInfo.cbSize = sizeof(cursorInfo);
if (GetCursorInfo(&cursorInfo)) {
ICONINFO ii = {0};
int p = GetIconInfo(cursorInfo.hCursor, &ii);
// get screen
HDC dc = GetDC(NULL);
HDC memDC = CreateCompatibleDC(dc);
//SelectObject(memDC, ii.hbmColor);
int counter = 0;
//
byte* bits[1000];// = new byte[w * 4];
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = 16;
bmi.bmiHeader.biHeight = 16;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
int rv = ::GetDIBits(memDC, ii.hbmColor, 0, 1, (void**)&bits, &bmi, DIB_RGB_COLORS);
}
Start by getting the parameters of the bitmap as recorded by Windows:
BITMAP bitmap = {0};
GetObject(ii.hbmColor, sizeof(bitmap), &bitmap);
You can use the returned values to populate the bmi structure.
And about the bmi structure: BITMAPINFO does not reserve enough space for a palette. You should create your own structure for this:
struct BitmapPlusPalette
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD palette[256];
};
Calculating the number of bytes needed for the bitmap is a bit tricky because it needs to be rounded up:
w = ((bitmap.bmWidth * bitmap.bmBitsPixel) + 31) / 8;
byte* bits = new byte[w * bitmap.bmHeight];
And here's a corrected version of your final line:
int rv = ::GetDIBits(dc, ii.hbmColor, 0, bitmap.bmHeight, bits, (BITMAPINFO *)&bmi, DIB_RGB_COLORS);
The problem with your code I think is in the way you allocated memory for 'bits' variable and how you used it then in GetDIBits function.
Firstly, the commented part byte* bits = new byte[w*4] was better than byte* bits[1000]. When you write byte* bits[1000] computer allocates 1000 POINTERS to byte. Each of these pointers doesn't point to anything.
Secondly, GetDIBits accepts LPVOID lpvBits as a 5th param. So, its a pointer to void.
In most platforms sizeof(void *) > sizeof(byte), so you can't just pass it a byte array, probably it would be better to pass a pointer to int or unsigned int (I'm not good at Windows types, so maybe something more appropriate should be better, sorry).
So, my guess is this:
unsigned bits[1000];
memset(bits, 0, sizeof(bits));
//...
int tv = GetDIBits(memDC, ii.hmbColor, 0, 1, (LPVOID)bits, /* ... */);