12-08-2015 03:42 AM - edited 12-08-2015 03:47 AM
Hi, I am writting a dll wrapper which using OpenCV function. I had been sucessfully implement Std::Vector<Point2i> by referencing "Sending an array of clusters to a C dll".
And now I would like to implement Std::Vector<Std::Vector<Point2i>> which is much like 2D array but elements of each row able to be different.
In LabVIEW, I assign a array of cluster of array of cluster of 2 I32 element which structure is shown below:
I think it has the same feature as Std::Vector<Std::Vector<Point2i>> in C++.
So I wire this data structure to the "Call Library Function Node" and generate C code which shown below:
/* Call Library source file */ #include "extcode.h" /* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */ #include "lv_prolog.h" /* Typedefs */ typedef struct { int32_t elt1; int32_t elt2; } TD4; typedef struct { int32_t dimSize; TD4 elt[1]; } TD3; typedef TD3 **TD3Hdl; typedef struct { TD3Hdl elt1; } TD2; typedef struct { int32_t dimSize; TD2 elt[1]; } TD1; typedef TD1 **TD1Hdl; #include "lv_epilog.h" void funcName(TD1Hdl arg1); void funcName(TD1Hdl arg1) { /* Insert code here */ }
Next, I write these code which show below into dll wrapper:
void funcName(TD1Hdl Blobs) { vector < vector<Point2i > > blobs; // Distribute contents of blobs to Blobs from LabVIEW MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(TD1, elt1) + sizeof(TD2)*blobs.size(); // Determine row size err = DSSetHSzClr(Blobs, arraySizeInBytes); if (err != mgNoErr) return; (*Blobs)->dimSize = blobs.size(); for (size_t i = 0; i < blobs.size(); i++) { arraySizeInBytes = Offset(TD3, elt) + sizeof(TD4)*blobs[i].size(); // Determine col size of each row err = DSSetHSzClr((*Blobs)->elt[i].elt1, arraySizeInBytes); if (err != mgNoErr) return; /*......................*/ } }
When I call dll from LabVIEW, the program get interuption(i.e shutdown) at the line where I want to determine column size of each row.
Could any one give me some suggestions about it or promote another implementation of this requirement?
Thanks a lot.
Solved! Go to Solution.
12-08-2015 05:16 AM
@sa002999 wrote:
Hi, I am writting a dll wrapper which using OpenCV function. I had been sucessfully implement Std::Vector<Point2i> by referencing "Sending an array of clusters to a C dll".
And now I would like to implement Std::Vector<Std::Vector<Point2i>> which is much like 2D array but elements of each row able to be different.
In LabVIEW, I assign a array of cluster of array of cluster of 2 I32 element which structure is shown below:
I think it has the same feature as Std::Vector<Std::Vector<Point2i>> in C++.
So I wire this data structure to the "Call Library Function Node" and generate C code which shown below:
/* Call Library source file */ #include "extcode.h" /* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */ #include "lv_prolog.h" /* Typedefs */ typedef struct { int32_t elt1; int32_t elt2; } TD4; typedef struct { int32_t dimSize; TD4 elt[1]; } TD3; typedef TD3 **TD3Hdl; typedef struct { TD3Hdl elt1; } TD2; typedef struct { int32_t dimSize; TD2 elt[1]; } TD1; typedef TD1 **TD1Hdl; #include "lv_epilog.h" void funcName(TD1Hdl arg1); void funcName(TD1Hdl arg1) { /* Insert code here */ }
Next, I write these code which show below into dll wrapper:
void funcName(TD1Hdl Blobs) { vector < vector<Point2i > > blobs; >> How is blobs initialized? Is the function which should initialize it giving back an error?
// Distribute contents of blobs to Blobs from LabVIEW MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(TD1, elt1) + sizeof(TD2)*blobs.size(); // Determine row size err = DSSetHSzClr(Blobs, arraySizeInBytes); if (err != mgNoErr) return; (*Blobs)->dimSize = blobs.size(); for (size_t i = 0; i < blobs.size(); i++) { arraySizeInBytes = Offset(TD3, elt) + sizeof(TD4)*blobs[i].size(); // Determine col size of each row err = DSSetHSzClr((*Blobs)->elt[i].elt1, arraySizeInBytes); if (err != mgNoErr) return; /*......................*/ } }
When I call dll from LabVIEW, the program get interuption(i.e shutdown) at the line where I want to determine column size of each row.
Could any one give me some suggestions about it or promote another implementation of this requirement?
Thanks a lot.
Might be a stupid question, but is there some code you didn't show, where I added the red text? blobs is an uninitialized object as far as I can see.
12-08-2015 06:56 PM
rolfk 已寫:
@sa002999 wrote:
Hi, I am writting a dll wrapper which using OpenCV function. I had been sucessfully implement Std::Vector<Point2i> by referencing "Sending an array of clusters to a C dll".
And now I would like to implement Std::Vector<Std::Vector<Point2i>> which is much like 2D array but elements of each row able to be different.
In LabVIEW, I assign a array of cluster of array of cluster of 2 I32 element which structure is shown below:
I think it has the same feature as Std::Vector<Std::Vector<Point2i>> in C++.
So I wire this data structure to the "Call Library Function Node" and generate C code which shown below:
/* Call Library source file */ #include "extcode.h" /* lv_prolog.h and lv_epilog.h set up the correct alignment for LabVIEW data. */ #include "lv_prolog.h" /* Typedefs */ typedef struct { int32_t elt1; int32_t elt2; } TD4; typedef struct { int32_t dimSize; TD4 elt[1]; } TD3; typedef TD3 **TD3Hdl; typedef struct { TD3Hdl elt1; } TD2; typedef struct { int32_t dimSize; TD2 elt[1]; } TD1; typedef TD1 **TD1Hdl; #include "lv_epilog.h" void funcName(TD1Hdl arg1); void funcName(TD1Hdl arg1) { /* Insert code here */ }
Next, I write these code which show below into dll wrapper:
void funcName(TD1Hdl Blobs) { vector < vector<Point2i > > blobs; >> How is blobs initialized? Is the function which should initialize it giving back an error?
Labeling(image_binary, blobs); // the prototype of this function is: Labeling(Mat &binary, Vector<Vector<Point2i>> &blobs)
// Distribute contents of blobs to Blobs from LabVIEW MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(TD1, elt1) + sizeof(TD2)*blobs.size(); // Determine row size err = DSSetHSzClr(Blobs, arraySizeInBytes); if (err != mgNoErr) return; (*Blobs)->dimSize = blobs.size(); for (size_t i = 0; i < blobs.size(); i++) { arraySizeInBytes = Offset(TD3, elt) + sizeof(TD4)*blobs[i].size(); // Determine col size of each row err = DSSetHSzClr((*Blobs)->elt[i].elt1, arraySizeInBytes); if (err != mgNoErr) return; /*......................*/ } }
When I call dll from LabVIEW, the program get interuption(i.e shutdown) at the line where I want to determine column size of each row.
Could any one give me some suggestions about it or promote another implementation of this requirement?
Thanks a lot.
Might be a stupid question, but is there some code you didn't show, where I added the red text? blobs is an uninitialized object as far as I can see.
Sorry, my mistake. I always think that blobs have initialized and yes the place where you added the red text have some code. I will do labeling which will give blobs infomations about amount of particle in this image and coordinate of elements of these particle. Thanks for your reply.
12-09-2015 01:51 AM - edited 12-09-2015 02:03 AM
@sa002999 wrote:
void funcName(TD1Hdl Blobs) { vector < vector<Point2i > > blobs; Labeling(image_binary, blobs); // the prototype of this function is: Labeling(Mat &binary, Vector<Vector<Point2i>> &blobs)
// Distribute contents of blobs to Blobs from LabVIEW MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(TD1, elt1) + sizeof(TD2)*blobs.size(); // Determine row size err = DSSetHSzClr(Blobs, arraySizeInBytes); if (err != mgNoErr) return; (*Blobs)->dimSize = blobs.size(); for (size_t i = 0; i < blobs.size(); i++) { arraySizeInBytes = Offset(TD3, elt) + sizeof(TD4)*blobs[i].size(); // Determine col size of each row err = DSSetHSzClr((*Blobs)->elt[i].elt1, arraySizeInBytes); if (err != mgNoErr) return; /*......................*/ } }
Sorry, my mistake. I always think that blobs have initialized and yes the place where you added the red text have some code. I will do labeling which will give blobs infomations about amount of particle in this image and coordinate of elements of these particle. Thanks for your reply.
You could have found that yourself with a little bit debugging in the source code level debugger!
(*Blobs)->elt[i].elt1
This will be generally NULL as you resized that handle just a few nanoseconds before with DSSetHSzClr()! That is correct to do so, because DSSetHandle() might leave the additional memory uninitialized and that would certainly crash as subsequent code would try to access the handle that is just random gibberish.
DSSetHSzClr() is not able to create a new handle as the handle parameter is passed by value. You do need to use conditional code that checks for the handle to be NULL and if that is the case does create a new handle with DSNewHClr() instead and afterwards checks for it to be non-NULL. If it is NULL you need to set your err to mFullErr and abort.
And yes you should really use the conditional code to account for handles being able to be both NULL and non-NULL. Your LabVIEW code might at some point pass in a non empty array from the diagram and if you just blindly assume that the whole array was never allocated in the first place you will leak memory.
And note that if you passed Blobs by pointer, LabVIEW would generally pass into your function a NULL handle too as that is the canoncal empty handle in LabVIEW. Since you passed it in by value, it can't do so as otherwise your function could never allocate a new handle and return it to LabVIEW.
Maybe you're a bit spoiled by C++ reference parameters which make this appear a little bit easier. But in C you really have to dig the difference between pass by value and pass by pointer and the implications these two have on coding.
12-09-2015 11:46 PM
It is very helpful. The handle what I try to resize is NULL exactly and error happened in subsequent code. It is indeed a good habit that check handle whether is non-NULL before pass it to the DSSetHSzClr().
Here is my code works successfully and thanks for your help:
void funcName(TD1Hdl Blobs) { vector < vector<Point2i > > blobs; Labeling(image_binary, blobs); // the prototype of this function is: Labeling(Mat &binary, Vector<Vector<Point2i>> &blobs) // Distribute contents of blobs to Blobs from LabVIEW MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(TD1, elt) + sizeof(TD2)*blobs.size(); // Determine row size
if (contours == NULL)
Blobs = (TD1Hdl)DSNewHClr(arraySizeInBytes);
else err = DSSetHSzClr(Blobs, arraySizeInBytes); if (err != mgNoErr || Blobs == NULL) return; (*Blobs)->dimSize = blobs.size(); for (size_t i = 0; i < blobs.size(); i++) { arraySizeInBytes = Offset(TD3, elt) + sizeof(TD4)*blobs[i].size(); // Determine col size of each row
if((*Blobs)->elt[i].elt1 == NULL)
(*Blobs)->elt[i].elt1 = (TD3Hdl)DSNewHClr(arraySizeInBytes);
else err = DSSetHSzClr((*Blobs)->elt[i].elt1, arraySizeInBytes); if (err != mgNoErr || (*Blobs)->elt[i].elt1 == NULL) return;
(*((*Blobs)->elt[i].elt1))->dimSize = blobs[i].size(); /*......................*/ } }
:
12-10-2015 01:09 AM - edited 12-10-2015 01:15 AM
MgErr funcName(TD1Hdl Blobs) { vector < vector<Point2i > > blobs; Labeling(image_binary, blobs); // the prototype of this function is: Labeling(Mat &binary, Vector<Vector<Point2i>> &blobs) // Distribute contents of blobs to Blobs from LabVIEW MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(TD1, elt) + sizeof(TD2)*blobs.size(); // Determine row size
if (contours == NULL)
{
Blobs = (TD1Hdl)DSNewHClr(arraySizeInBytes);
if (Blobs == NULL)
err = mFullErr;
}
else
err = DSSetHSzClr(Blobs, arraySizeInBytes);
if (err != mgNoErr)
return err;
for (size_t i = 0; err == mgNoEerr && i < blobs.size(); i++) { arraySizeInBytes = Offset(TD3, elt) + sizeof(TD4)*blobs[i].size(); // Determine col size of each row
if ((*Blobs)->elt[i].elt1 == NULL)
{
(*Blobs)->elt[i].elt1 = (TD3Hdl)DSNewHClr(arraySizeInBytes);
if ((*Blobs)->elt[i].elt1 == NULL)
err = mFullErr;
}
else
err = DSSetHSzClr((*Blobs)->elt[i].elt1, arraySizeInBytes);
if (err == mgNoErr)
{
(*((*Blobs)->elt[i].elt1))->dimSize = blobs[i].size(); /*......................*/
} } (*Blobs)->dimSize = i;
return err;
}
Personaally I usually do it like this. The err from DSSetHSzClr() already indicates if there was something going wrong and the handle can't really get NULL from calling this function.
To be fully correct and failsafe you would need to do even more than this. But as long as you assume that the incoming array is always smaller than the outgoing array will be (usually it will be 0 elements when entering this function but if you somehow reuse the array in the diagram, by storing it in a shift register for instance, this might not be true anymore) this will suffice.
12-10-2015 04:55 AM - edited 12-10-2015 04:55 AM
One more thing!
this line:
if (contours == NULL)
should of course be:
if (Blobs == NULL)
01-29-2016 09:35 AM
Hi!
I'm facing the same exact problem.
If possible, it would same me a lot of troubles to give a look inside this part of the code:
/*......................*/
In other words, in the part where the Labview array is populated.
Thanks in advance for your help!
Marco
02-01-2016 05:14 AM
For your information, that's what I did:
size_t p = 0; for (p = 0; err == mgNoErr && p < contours[i].size(); p++) { ((*((*Blobs)->elt[i].elt1))->elt[p]).X = (blobs[i])[p].x; ((*((*Blobs)->elt[i].elt1))->elt[p]).Y = (blobs[i])[p].y; }