Jump to content

Send cluster / struct from dll with a couple of int's AND a string of text to Labview


Recommended Posts

Hello to you all,

Sending a cluster with int's

I did manage to send an array with clusters from a dll to Labview. Thank you all for the help. You can find the link here:

https://lavag.org/topic/22877-can-someone-help-me-with-an-example-for-an-existing-wrapper-dll-which-uses-function-pointer-with-callback-function/#comment-147496

It works fine I am very pleased with it. 😃

Sending a text string 

I did got a example here: 

https://forums.ni.com/t5/Example-Code/Posting-Events-to-a-LabVIEW-Event-Structure-From-a-Dll/ta-p/3996283

Tested it and it works fine. Again I am happy 😃

Sending a cluster with int's AND a string

Now I want to send a cluster / struct with a couple of int's AND a string of text. I Got a example of how to send text from a C / C++ wrapper to Labview, can someone please help me out? The thing I do not get is, how to combine the both examples. Is "sizeof(structSample)" valid with a LStrHandle in it? How do I copy the data from the string to the struct, etc. Can someone change the code example or help me with the example so it works? I did add some text to the example code to make it more clear I added +++ signs in my comment in the code.

 

Hope someone can help me. Thanx !

 

 

// LVUserEvent.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <stdio.h>
#include "LVUserEvent.h"

#define STRING_LENGHT 256				//Can be any size

// ++++ I want to send this Cluster/Struct to Labview
typedef struct {
		int firstInt;
		int secondInt;
		int thirdInt
// +++++ I try to add this, Gues this will not work .. see extcode.h 		
        LStrHandle textString[TEXT_STRING_SIZE];        
		}structSample;										

typedef struct{
        int32_t size;
        structSample elm[1];
   }totalstructSample, **structHdl




LVUSEREVENT_API void SendEvent(LVUserEventRef *rwer)
{
	LStrHandle newStringHandle;

	//Allocate memory for a LabVIEW string handle using LabVIEW's
	//memory manager functions.
	newStringHandle=(LStrHandle)DSNewHandle(sizeof(int32)+STRING_LENGHT*sizeof(uChar));
	
	// +++++ OW no another one ... 
	structHdl = (eventHdl)DSNewHandle(sizeof(totalstructSample));
	
	
	
	Sleep(2000);
	PopulateStringHandle(newStringHandle,"+++ Dear int I don't want you in my PostLVUserEvent");
	
	//Post event to Event structure. Refer to "Using External Code
	//with LabVIEW manual for information about this function.
	PostLVUserEvent(*rwer,(void *)&newStringHandle);



	return;
}

void PopulateStringHandle(LStrHandle lvStringHandle,char* stringData)
{
	//Empties the buffer
	memset(LStrBuf(*lvStringHandle),'\0',STRING_LENGHT);
	
	//Fills the string buffer with stringData
	sprintf((char*)LStrBuf(*lvStringHandle),"%s",stringData);
	
	//Informs the LabVIEW string handle about the size of the size
	LStrLen(*lvStringHandle)=strlen(stringData);
	
	return;
}

 

 

 

 

 

 

 

 

 

 

 

Link to comment
2 hours ago, Neon_Light said:

Hello to you all,

Sending a cluster with int's

I did manage to send an array with clusters from a dll to Labview. Thank you all for the help. You can find the link here:

https://lavag.org/topic/22877-can-someone-help-me-with-an-example-for-an-existing-wrapper-dll-which-uses-function-pointer-with-callback-function/#comment-147496

It works fine I am very pleased with it. 😃

Sending a text string 

I did got a example here: 

https://forums.ni.com/t5/Example-Code/Posting-Events-to-a-LabVIEW-Event-Structure-From-a-Dll/ta-p/3996283

Tested it and it works fine. Again I am happy 😃

Sending a cluster with int's AND a string

Now I want to send a cluster / struct with a couple of int's AND a string of text. I Got a example of how to send text from a C / C++ wrapper to Labview, can someone please help me out? The thing I do not get is, how to combine the both examples. Is "sizeof(structSample)" valid with a LStrHandle in it? How do I copy the data from the string to the struct, etc. Can someone change the code example or help me with the example so it works? I did add some text to the example code to make it more clear I added +++ signs in my comment in the code.

 

Hope someone can help me. Thanx !

 

 

// LVUserEvent.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include <stdio.h>
#include "LVUserEvent.h"

#define STRING_LENGHT 256				//Can be any size

// ++++ I want to send this Cluster/Struct to Labview
typedef struct {
		int firstInt;
		int secondInt;
		int thirdInt
// +++++ I try to add this, Gues this will not work .. see extcode.h 		
        LStrHandle textString[TEXT_STRING_SIZE];        
		}structSample;										

typedef struct{
        int32_t size;
        structSample elm[1];
   }totalstructSample, **structHdl




LVUSEREVENT_API void SendEvent(LVUserEventRef *rwer)
{
	LStrHandle newStringHandle;

	//Allocate memory for a LabVIEW string handle using LabVIEW's
	//memory manager functions.
	newStringHandle=(LStrHandle)DSNewHandle(sizeof(int32)+STRING_LENGHT*sizeof(uChar));
	
	// +++++ OW no another one ... 
	structHdl = (eventHdl)DSNewHandle(sizeof(totalstructSample));
	
	
	
	Sleep(2000);
	PopulateStringHandle(newStringHandle,"+++ Dear int I don't want you in my PostLVUserEvent");
	
	//Post event to Event structure. Refer to "Using External Code
	//with LabVIEW manual for information about this function.
	PostLVUserEvent(*rwer,(void *)&newStringHandle);



	return;
}

void PopulateStringHandle(LStrHandle lvStringHandle,char* stringData)
{
	//Empties the buffer
	memset(LStrBuf(*lvStringHandle),'\0',STRING_LENGHT);
	
	//Fills the string buffer with stringData
	sprintf((char*)LStrBuf(*lvStringHandle),"%s",stringData);
	
	//Informs the LabVIEW string handle about the size of the size
	LStrLen(*lvStringHandle)=strlen(stringData);
	
	return;
}

You clearly have not much C programming experience. Which of course is a very bad starting point to try to write C code that should then interoperate with LabVIEW.

First this:

// +++++ I try to add this, Gues this will not work .. see extcode.h 		
        LStrHandle textString[TEXT_STRING_SIZE];        
		}structSample;										

You are basically defining a fixed size array of TEXT_STRING_SIZE LabVIEW string handles, not a LabVIEW string handle of TEXT_STRING_SIZE length. LabVIEW string handles are never fixed size but instead dynamically allocated memory blocks with an extra pointer reference to it. And that dynamic allocation (and deallocation) ABSOLUTELY and SURELY must be done by using the LabVIEW memory manager functions. Anything else is nothing more than a crash site.

What you have built there as datatype would look like an array of structs and each of these structs would contain three integers followed by 256 LabVIEW string handles, which is not only pretty weird but absolutely NOT compatible with any possible LabVIEW structure.

And after allocating all these things you eventually only send the actual string handle to the event and leak everything else and the handle itself too!

typedef struct
{
	int32_t firstInt;
	int32_t secondInt;
	int32_t thirdInt;
	LStrHandle lvString;
} MyStruct, *MyStructPtr;


MgErr CreateStringHandle(LStrHandle *lvStringHandle, char* stringData)
{
	MgErr err;
	size_t len = strlen(stringData);
	if (*lvStringHandle)
	{
		err = DSSetHandleSize(*lvStringHandle, sizeof(int32_t) + len);
	}
	else
	{
		*lvStringHandle = DSNewHandle(sizeof(int32_t) + len);
		if (!*lvStringHandle)
			err = mFullErr;
	}
	if (!err)
	{
		MoveBlock(stringData, LStrBuf(**lvStringHandle), len);
		LStrLen(**lvStringHandle) = (int32_t)len;
	}
	return err;
}

MgErr SendStringInSructToLV(LVUserEventRef *userEvent)
{
 	MyStruct structure = {1, 2, 3, NULL);
	MgErr err = CreateStringHandle(&structure.lvString, "Some C String!");
	if (!err)
	{
		err = PostLVUserEvent(*userEvent, &structure);
		DSDisposeHandle(structure.lvString);
	}
	return err;
}

 

Edited by Rolf Kalbermatter
  • Like 2
Link to comment
14 hours ago, Rolf Kalbermatter said:

You clearly have not much C programming experience.

typedef struct
{
	int32_t firstInt;
	int32_t secondInt;
	int32_t thirdInt;
	LStrHandle lvString;
} MyStruct, *MyStructPtr;


MgErr CreateStringHandle(LStrHandle *lvStringHandle, char* stringData)
{
	MgErr err;
	size_t len = strlen(stringData);
	if (*lvStringHandle)
	{
		err = DSSetHandleSize(*lvStringHandle, sizeof(int32_t) + len);
	}
	else
	{
		*lvStringHandle = DSNewHandle(sizeof(int32_t) + len);
		if (!*lvStringHandle)
			err = mFullErr;
	}
	if (!err)
	{
		MoveBlock(stringData, LStrBuf(**lvStringHandle), len);
		LStrLen(**lvStringHandle) = (int32_t)len;
	}
	return err;
}

MgErr SendStringInSructToLV(LVUserEventRef *userEvent)
{
 	MyStruct structure = {1, 2, 3, NULL);
	MgErr err = CreateStringHandle(&structure.lvString, "Some C String!");
	if (!err)
	{
		err = PostLVUserEvent(*userEvent, &structure);
		DSDisposeHandle(structure.lvString);
	}
	return err;
}

 

Me neither so I'm stealing that snippet.:D

Link to comment
16 hours ago, Rolf Kalbermatter said:

You clearly have not much C programming experience. Which of course is a very bad starting point to try to write C code that should then interoperate with LabVIEW.

I am afraid you are correct, the C I did was low level ANSI... I bought a book to learn C++, but I am afraid to have landed in a chicken egg situation: I really want to finish this project so I can start with the book but I am losing a lot of time finishing this project because the lack of knowledge. I can copy and understand parts from the internet, but without the overview which a book can give ... ow well I think you get the point. Anyway your answer helps me a lot I hope I can start reading the book soon. 

Is my assumption correct that:

I only need a handle if the size of the data is unknown e.g. the struct with a unknown string size?

But when I do something like this:

typedef struct {
		int firstInt;
		int secondInt;
		int thirdInt
		// The string is gone !! Now I know it is 3 x int = 12 bytes      
		}structSample;
..

Then I do not need a handle?

Thanx again Rolf!! Your help is great!

 

 

 

Link to comment
On 5/13/2023 at 4:07 PM, ShaunR said:

Me neither so I'm stealing that snippet.:D

While it's not a problem for this specific datatype, you should do something extra for any struct definition, which I forgot in my example above!

#include "extcode.h"   // This is logical to get the definitions for the LabVIEW manager functions
#include "hosttype.h"  // Helpful if you also intend to include OS system API headers
......                 // Anything else you may need to include

#include "lv_prolog.h" // This is important to get correct alignment definition for any structured datatype
                       // that is meant to interface directly to LabVIEW native diagram clusters 

typedef struct         // This datatypes elements are now properly aligned to LabVIEW rules
{
	int32_t firstInt;
	int32_t secondInt;
	int32_t thirdInt;
	LStrHandle lvString;
} MyStruct, *MyStructPtr;

#include "lv_epilog.h" // Reset the alignment to what it was before the "lv_prolog.h" include

..........................

As mentioned for this particular cluster no special alignment rules apply for 32-bit as all 4 elements are 32-bit entities. In LabVIEW 64-bit the LStrHandle (which is a pointer really) is aligned to 64-bit, so there are 4 extra bytes added between thirdInt and lvString, but LabVIEW also uses the default alignment of 8 byte (64-bit) so the alignment is again the same independent if you use those lv_prolog.h and lv_epilog.h includes or not. But in LabVIEW 32-bit full byte packing is used (for traditional reason), while most compilers there also use 64-bit alignment rules. Therefore if the natural alignment of elements does cause extra filler bytes, it will not match with what LabVIEW 32-bit for Windows expects for its clusters.

 

Edited by Rolf Kalbermatter
Link to comment
On 5/13/2023 at 5:39 PM, Neon_Light said:

I am afraid you are correct, the C I did was low level ANSI... I bought a book to learn C++, but I am afraid to have landed in a chicken egg situation: I really want to finish this project so I can start with the book but I am losing a lot of time finishing this project because the lack of knowledge. I can copy and understand parts from the internet, but without the overview which a book can give ... ow well I think you get the point. Anyway your answer helps me a lot I hope I can start reading the book soon. 

Is my assumption correct that:

I only need a handle if the size of the data is unknown e.g. the struct with a unknown string size?

But when I do something like this:

typedef struct {
		int firstInt;
		int secondInt;
		int thirdInt
		// The string is gone !! Now I know it is 3 x int = 12 bytes      
		}structSample;
..

Then I do not need a handle?

Thanx again Rolf!! Your help is great!

Handles are only used for arrays (and a LabVIEW string is also an array of ASCII bytes).

Now, when you start to do arrays of structures, things get really fun, but yes it is an array so it is a handle too.

Edited by Rolf Kalbermatter
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.