LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Implement Std::Vector<Std::Vector<Point2i>> in dll wrapper for LabVIEW

Solved!
Go to solution

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:

 

Structure

 

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.

 

0 Kudos
Message 1 of 9
(4,961 Views)

@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:

 

Structure

 

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.

Rolf Kalbermatter
My Blog
0 Kudos
Message 2 of 9
(4,935 Views)

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:

 

Structure

 

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.

0 Kudos
Message 3 of 9
(4,905 Views)

@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. Smiley LOL 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.

Rolf Kalbermatter
My Blog
0 Kudos
Message 4 of 9
(4,885 Views)

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(); /*......................*/ } }

:

 

0 Kudos
Message 5 of 9
(4,844 Views)
Solution
Accepted by topic author sa002999

 

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.

 

Rolf Kalbermatter
My Blog
Message 6 of 9
(4,832 Views)

One more thing!

 

this line:

 

if (contours == NULL)

should of course be:

 

if (Blobs == NULL)
Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 9
(4,815 Views)

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

0 Kudos
Message 8 of 9
(4,551 Views)

   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;
			}

 

0 Kudos
Message 9 of 9
(4,516 Views)