LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

CIN: Converting a C String to a LabVIEW String

Hi all,

I have been developing CINs in Microsoft Visual C++ 6.0 for LabVIEW as
project needs. However, I am having a problem with converting a C String
to a LabVIEW String in CIN.

I used two ways to try to make the conversion work that were LStrPrintf
and MoveBlock as stated as following:

1. LStrPrintf

#include "extcode.h"
#include "hosttype.h"
#include "windows.h"

struct teststrct{
...
const char* test;
...
};

struct teststrct testinstance;

typedef struct {
...
LStrHandle test
...
} TD1;

CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {

char *tempCStr = NULL;

....

strcpy(tempCStr, testinstance.test); // this would cause LabVIEW crash!
LStrPrintf(testcluster->test, (CStr) "%s", tempCSt
r);
// but if I assigned tempCStr as tempCStr = "test", the string value
"test" could be passed to LabVIEW without any problems.

....
}



2. MoveBlock

#include "extcode.h"
#include "hosttype.h"
#include "windows.h"


struct teststrct{
...
const char* test;
...
};

struct teststrct testinstance;

typedef struct {
...
LStrHandle test
...
} TD1;

CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {

char *tempCStr = NULL;
int32 len;
....

tempCStr = (char *)&testinstance.test; //since strcpy didn't work, I
used this way to try to copy the const char* to char*.
len = StrLen(tempCStr);

if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
len))
{
*Error = LVFALSE;
goto out;
}

MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len); // the string
was able to passed to LabVIEE, but it was unreadable.
...

out:
....

}


Did I do anything wrong? Any thougths or suggestions would be very
appreciated!
0 Kudos
Message 1 of 9
(4,727 Views)
The LStrPrintf example works correctly with the "test" string literal because
tempCStr= "test"; assigns the pointer tempCStr to point to the buffer containing
"text". Calling strcpy to move any string to tempStr will cause
problems because it is copying the string to an uninitialized pointer,
not to a string buffer. There isn't anything wrong with the LStrPrintf
call, the damage is already done.

In the moveblock case, the code:
tempCStr = (char *)&testinstance.test; //since strcpy didn't work, I
used this way to try to copy the const char* to char*.

doesn't copy the buffer, it just changes a pointer, tempCStr to point to
the testinstance string buffer. This is not completely necessary, but
does no harm and is very different from a call to strcpy.

I believe the reason that LV cannot see the returned string is that the
string size hasn't been set.
Again, I'm not looking at any documentation, but I believe that you may
want to look at LStrLen(*testcluster->test). I think it will be size of
the string passed into the CIN, and it should be set to len before returning.

Greg McKaskle


> struct teststrct{
> ...
> const char* test;
> ...
> };
>
> struct teststrct testinstance;
>
> typedef struct {
> ...
> LStrHandle test
> ...
> } TD1;
>
> CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {
>
> char *tempCStr = NULL;
>
> ...
>
> strcpy(tempCStr, testinstance.test); // this would cause LabVIEW crash!
> LStrPrintf(testcluster->test, (CStr) "%s", tempCStr);
> // but if I assigned tempCStr as tempCStr = "test", the string value
> "test" could be passed to LabVIEW without any problems.
>
> ...
> }
>
> 2. MoveBlock
>
> #include "extcode.h"
> #include "hosttype.h"
> #include "windows.h"
>
> struct teststrct{
> ...
> const char* test;
> ...
> };
>
> struct teststrct testinstance;
>
> typedef struct {
> ...
> LStrHandle test
> ...
> } TD1;
>
> CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {
>
> char *tempCStr = NULL;
> int32 len;
> ...
>
> tempCStr = (char *)&testinstance.test; //since strcpy didn't work, I
> used this way to try to copy the const char* to char*.
> len = StrLen(tempCStr);
>
> if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
> len))
> {
> *Error = LVFALSE;
> goto out;
> }
>
> MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len); // the string
> was able to passed to LabVIEE, but it was unreadable.
> ...
>
> out:
> ...
>
> }
>
> Did I do anything wrong? Any thougths or suggestions would be very
> appreciated!
0 Kudos
Message 2 of 9
(4,727 Views)
Thank you so much for your response, Greg. However, I still have problem after making
corresponding modification for LStrPrintf approach:

int32 len;
char tempCStr[255] = "";

strcpy(temCStr, testinstance.test);
len = StrLen(tempCStr);
LStrPrintf(testcluster->test, (CStr) "%s", tempCStr);
LStrLen(*testcluster->test) = len;


LabVIEW crashes. Any ideas?


Greg McKaskle wrote:

> The LStrPrintf example works correctly with the "test" string literal because
> tempCStr= "test"; assigns the pointer tempCStr to point to the buffer containing
> "text". Calling strcpy to move any string to tempStr will cause
> problems because it is copying the string to an uninitialized pointer,
> not to a string buffer. There isn't anything wrong with the LStrPrintf
> call, the damage is already done.
>
> In the moveblock case, the code:
> tempCStr = (char *)&testinstance.test; //since strcpy didn't work, I
> used this way to try to copy the const char* to char*.
>
> doesn't copy the buffer, it just changes a pointer, tempCStr to point to
> the testinstance string buffer. This is not completely necessary, but
> does no harm and is very different from a call to strcpy.
>
> I believe the reason that LV cannot see the returned string is that the
> string size hasn't been set.
> Again, I'm not looking at any documentation, but I believe that you may
> want to look at LStrLen(*testcluster->test). I think it will be size of
> the string passed into the CIN, and it should be set to len before returning.
>
> Greg McKaskle
>
> > struct teststrct{
> > ...
> > const char* test;
> > ...
> > };
> >
> > struct teststrct testinstance;
> >
> > typedef struct {
> > ...
> > LStrHandle test
> > ...
> > } TD1;
> >
> > CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {
> >
> > char *tempCStr = NULL;
> >
> > ...
> >
> > strcpy(tempCStr, testinstance.test); // this would cause LabVIEW crash!
> > LStrPrintf(testcluster->test, (CStr) "%s", tempCStr);
> > // but if I assigned tempCStr as tempCStr = "test", the string value
> > "test" could be passed to LabVIEW without any problems.
> >
> > ...
> > }
> >
> > 2. MoveBlock
> >
> > #include "extcode.h"
> > #include "hosttype.h"
> > #include "windows.h"
> >
> > struct teststrct{
> > ...
> > const char* test;
> > ...
> > };
> >
> > struct teststrct testinstance;
> >
> > typedef struct {
> > ...
> > LStrHandle test
> > ...
> > } TD1;
> >
> > CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {
> >
> > char *tempCStr = NULL;
> > int32 len;
> > ...
> >
> > tempCStr = (char *)&testinstance.test; //since strcpy didn't work, I
> > used this way to try to copy the const char* to char*.
> > len = StrLen(tempCStr);
> >
> > if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
> > len))
> > {
> > *Error = LVFALSE;
> > goto out;
> > }
> >
> > MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len); // the string
> > was able to passed to LabVIEE, but it was unreadable.
> > ...
> >
> > out:
> > ...
> >
> > }
> >
> > Did I do anything wrong? Any thougths or suggestions would be very
> > appreciated!
0 Kudos
Message 3 of 9
(4,727 Views)
> if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
> len))
> {
> *Error = LVFALSE;
> goto out;
> }
>
> MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len); // the string
> was able to passed to LabVIEE, but it was unreadable.

Also you should set the length of string because NumericArrayResize
don't make it. In your case:
LStrLen(*testcluster->test) = len;

Regards,
Kostya.


Sent via Deja.com http://www.deja.com/
Before you buy.
0 Kudos
Message 4 of 9
(4,727 Views)
Thanks. As long as the value of tempCStr is passed by a LabVIEW string or by
a static string such as "test", MoveBlock or LStrPrintf works fine. Since
tempCStr will be assigned by a structure element which is always changed at
runtime through a C application server across network in my case, for some
reason this kind of data passing (I tested strcpy or StrCpy with MoveBlock
or LStrPrintf) causes LabVIEW crash. But only C application with the data
passing stated as above works perfect well. Just no sure why.

Any thoughts?

vilab@email.com wrote:

> > if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
> > len))
> > {
> > *Error = LVFALSE;
> > goto out;
> > }
> >
> > MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len); // the string
> > was ab
le to passed to LabVIEE, but it was unreadable.
>
> Also you should set the length of string because NumericArrayResize
> don't make it. In your case:
> LStrLen(*testcluster->test) = len;
>
> Regards,
> Kostya.
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.
0 Kudos
Message 5 of 9
(4,727 Views)
> Thanks. As long as the value of tempCStr is passed by a LabVIEW
string or by
> a static string such as "test", MoveBlock or LStrPrintf works fine.
Since
> tempCStr will be assigned by a structure element which is always
changed at
> runtime through a C application server across network in my case, for
some
> reason this kind of data passing (I tested strcpy or StrCpy with
MoveBlock
> or LStrPrintf) causes LabVIEW crash. But only C application with the
data
> passing stated as above works perfect well. Just no sure why.
>
> Any thoughts?


I made few changes of your code (#2 MoveBlock). Now it work fine (I use
VC5.0, LV5.0). The CIN source code see below.

Regards,
Kostya.

// *** Start of CIN ***
#include "extcode.h"
#include "hosttype.h"
#incl
ude "windows.h"

struct teststrct{
const char* test;
};

struct teststrct testinstance = {"Hello World"};

typedef struct {
LStrHandle test;
} TD1;

CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {

MgErr err = noErr;
char *tempCStr = NULL;
int32 len;

tempCStr = (char *)testinstance.test; //*** Changed
// the original is
// tempCStr = (char *)&testinstance.test;
len = StrLen(tempCStr);

if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
len)) {
*Error = LVFALSE; goto out;
}

MoveBlock(tempCStr, LStrBuf(*testcluster->test), len); //*** Changed
// the original is
// MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len);

LStrLen(*testcluster->test) = len; //*** Added

out:
return err;
}
// *** The End ***


Sent via Deja.com http://www.deja.com/
Before you buy.
0 Kudos
Message 6 of 9
(4,727 Views)
Really appreciate that. It worked for me now. Besides those changes, I also
had to initialize the testinstance as you did (struct teststrct
testinstance = {"Hello World"};) even the testinstance would be always
changed at runtime through network. What I did was to set "" to those
string elements and 0 or 0.0 to integers or float.
Thanks for helping me out!

Kostya wrote:

> > Thanks. As long as the value of tempCStr is passed by a LabVIEW
> string or by
> > a static string such as "test", MoveBlock or LStrPrintf works fine.
> Since
> > tempCStr will be assigned by a structure element which is always
> changed at
> > runtime through a C application server across network in my case, for
> some
> > reason this kind of data passing (I tested strcpy or StrCpy with
> MoveBlock
> > or LStrPrintf) causes LabVIEW crash. But only C application with the
> data
> > passing stated as above works perfect well. Just no sure why.
> >
> > Any thoughts?
>
> I made few changes of your code (#2 MoveBlock). Now it work fine (I use
> VC5.0, LV5.0). The CIN source code see below.
>
> Regards,
> Kostya.
>
> // *** Start of CIN ***
> #include "extcode.h"
> #include "hosttype.h"
> #include "windows.h"
>
> struct teststrct{
> const char* test;
> };
>
> struct teststrct testinstance = {"Hello World"};
>
> typedef struct {
> LStrHandle test;
> } TD1;
>
> CIN MgErr CINRun(TD1 *testcluster, LVBoolean *Error) {
>
> MgErr err = noErr;
> char *tempCStr = NULL;
> int32 len;
>
> tempCStr = (char *)testinstance.test; //*** Changed
> // the original is
> // tempCStr = (char *)&testinstance.test;
> len = StrLen(tempCStr);
>
> if (err = NumericArrayResize(uB, 1L, (UHandle*)&testcluster->test,
> len)) {
> *Error = LVFALSE; goto out;
> }
>
> MoveBlock(tempCStr, LStrBuf(*testcluster->test), len); //*** Changed
> // the original is
> // MoveBlock(&tempCStr, LStrBuf(*testcluster->test), len);
>
> LStrLen(*testcluster->test) = len; //*** Added
>
> out:
> return err;
> }
> // *** The End ***
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.
0 Kudos
Message 7 of 9
(4,727 Views)
In article <397F104D.BB738CBB@lincom-asg.com>,
HC wrote:
> Really appreciate that. It worked for me now. Besides those changes,
> I also had to initialize the testinstance as you did (struct teststrct
> testinstance = {"Hello World"};) even the testinstance would be always
> changed at runtime through network. What I did was to set "" to those
> string elements and 0 or 0.0 to integers or float.
> Thanks for helping me out!

There are no needs in statical initialisation of the testinstance.test
pointer. I made it only for example (for obtaining this message in VI).
What is real necessary it's that this pointer must have correct value
before its using in runtime.

Regards,
Kostya.


Sent via Deja.com http
://www.deja.com/
Before you buy.
0 Kudos
Message 8 of 9
(4,727 Views)
If I don't initialize the testinstance with some bogus values, the LabVIEW
would be crashed. I guess it was because I actually tried to use
testinstance before it was assigned through the application server across
network. I didn't realize it was because timing problem until you pointed it
out. As long as I can make sure that the data is received before it is used,
it's fine without static initialization.
Thanks.

Kostya wrote:

> In article <397F104D.BB738CBB@lincom-asg.com>,
> HC wrote:
> > Really appreciate that. It worked for me now. Besides those changes,
> > I also had to initialize the testinstance as you did (struct teststrct
> > testinstance = {"Hello World"};) even the testinstance would be always

> > changed at runtime through network. What I did was to set "" to those
> > string elements and 0 or 0.0 to integers or float.
> > Thanks for helping me out!
>
> There are no needs in statical initialisation of the testinstance.test
> pointer. I made it only for example (for obtaining this message in VI).
> What is real necessary it's that this pointer must have correct value
> before its using in runtime.
>
> Regards,
> Kostya.
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.
0 Kudos
Message 9 of 9
(4,727 Views)