From 04:00 PM CDT – 08:00 PM CDT (09:00 PM UTC – 01:00 AM UTC) Tuesday, April 16, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

LabVIEW and C++ Pointers

For having done LabVIEW for 10+ years, I'm surprised to have to ask this question but cannot find anything on how to do this.

I am writing a LabVIEW interface to a .NET/C++ application.  One of the interface pieces is a file adapter (to a new proprietary file format).  The .NET portion of the reader returns a C++ "System.void*" pointer to me, that points to one record from the file.  However, before I can access this record from the C++ portion of the code, I need to type cast the void* pointer to the correct record type (one of 18 types).  These types are stored in a C++ interface.

Normally I would use the LabVIEW type cast block, but it is not obvious to me how to create something to pass into the "Type" input for the type cast.  Do I need to do all the type casting in C, then at the last moment move the structure into LabVIEW?

Am I experiencing a brain fart, or is this just not possible in LabVIEW?
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 1 of 22
(9,842 Views)
Hi Joe,
 
Trying to reply a CLA's question is just my brain fart! but at least it brings the thread to the top of the list!
 
As far as I know there is no pointers in LV. and in my 2 years of experience I only faced this problem while working with DLLs, but it is always solvable with some techniques as I know. take a look at this thread. you may want see these articles fom NI support too. [1][2], [3]
 
With Regards.
Message 2 of 22
(9,822 Views)
Trying to reply a CLA's question is just my brain fart! but at least it brings the thread to the top of the list!
 
Even after 10 years, I still learn something new about LV almost every day.  I've had people with 3 months experience show me better ways to do things, so I'm not bashful in asking around.  Even not getting an answer is often an answer...

As far as I know there is no pointers in LV. and in my 2 years of experience I only faced this problem while working with DLLs, but it is always solvable with some techniques as I know. take a look at this thread. you may want see these articles fom NI support too. [1][2], [3]

These are better references than I found searching yesterday (I think the third one may even have been submitted by a developer at my previous job -- at least it looks like a similar problem we had with Netcom's Smartbits).  Unfortunately it looks like LabVIEW is limited to dealing with "C" type interfaces, and not true "C++"/object oriented ones (that's not to say you cannot talk to a C++ .dll, you just cannot use the "++" portion).  The other examples I found on NI's website indicate that you can pass references around between .dlls, but there is little you can do with them unless they were generated within LabVIEW first (e.g., pass in a pointer to an empty LabVIEW array, and the .dll can populate it; or you can pass a reference generated by one .dll to another).  I've been dabbling with the LabVIEW .NET interface for the last few months and you CAN (though it is frowned upon, see for example [1]) treat .NET references in an object-oriented sense, so I guess I have become spoiled in that sense.


Joe
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 3 of 22
(9,810 Views)

I have found talking to pointers from labview to be one of the most difficult problems when developing with labview.  There is almost always to do it but this problem requires much more work than other issues that arise in labview.  Since memory management is shielded from the developer (to some extent) pointers seem foreign to Labview.  I have had some trouble when using WIN32 calls which take a pointer to a pointer, usually in the form of an object referenced as a handle which contains a pointer or an array.  The only work-around I have found is to write a dll library in c++ which acts as a accessor function, taking the handle to the object and returning a copy of the value stored (or the location of) the data needed.  This is time consuming and not all that elegant.  I too am interested in similar issues with both .net and c++ interfacing with labview.  Sorry if this doesn't answer your question but this discussion topic is of great interest to me.

Paul

Paul Falkenstein
Coleman Technologies Inc.
CLA, CPI, AIA-Vision
Labview 4.0- 2013, RT, Vision, FPGA
Message 4 of 22
(9,808 Views)
Hi Joe,

@Joe Gerhardstein wrote:
...
However, before I can access this record from the C++ portion of the code, I need to type cast the void* pointer to the correct record type (one of 18 types). ... Normally I would use the LabVIEW type cast block,


I don't think I understand your problem. As I understand it, you are getting a void* back from a .NET method (property, whatever), and you then need to pass that off to some C++ code after casting? I assume the C++ code is in DLL? Why the need to cast on the LabVIEW side of things rather than inside the DLL?

Having admitted my lack of comprehension, I will now take a stab and what your problem might be. Perhaps you are trying to cast the pointer and then use it as a C++ object pointer and access member functions or properties? If that is the case, then what you are trying to do requires a C interface DLL wrapper. LabVIEW can't use thiscall calling conventions that would be necessary to directly access the members of the object.

Jason

Message 5 of 22
(9,797 Views)
Paul:

If you are interested in the pointer-to-a-structure-containing-a-pointer case, I would suggest you spend some time looking at .NET.  My understanding is that C code ports pretty easily into .NET, and once there, you can use the .NET tools (Block Diagram: Functions -> Communicaitons -> .NET; Front Panel: Controls -> Refnum -> .NET Refnum) to do a lot more than you can with unmanaged C code.  I have found that you can access complex .NET objects including variable-length arrays (ArrayList), create objects (.NET Constructors), take pointers (.NET Refnums) and cast them to new types (with the warnings provided by lycangeek in the reference in my previous post), perform reflection, and generally treat your external code as more object oriented.  The only firm limitation I have found is that LabVIEW cannot access post-binding items: it needs to know what type an object is at edit time (and its methods and properties).  You need to treat post-binding items in a pre-binding way (e.g., a For loop followed by a big case structure to check the returned pointer type against a list of possible options using the IsAssignableFrom function).


Joe
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 6 of 22
(9,792 Views)

I don't think I understand your problem. As I understand it, you are getting a void* back from a .NET method (property, whatever), and you then need to pass that off to some C++ code after casting? I assume the C++ code is in DLL? Why the need to cast on the LabVIEW side of things rather than inside the DLL?

Yes, the C code is in a .dll.  This .dll is used as a file adapter.  I can access the file's "directory" via .NET to find the number and type of records, but actually retrieving the data from the record (may be milions of data points) is way too slow through .NET.  A record in the file can be one of 18 different types (single scalar, complex scalar, single 1-D array with evenly spaced points, single1-D array with unevenly spaced points, complex 1-D array with evenly spaced points, etc.).  This .dll was designed to be accessed through C++ and .NET (and this is still the vast majority of its use), so the designer decided just to pass a pointer to the data and let the actual consumer of the data extract the values (instead of the code between the file adapter and data consumer having to worry about the structure), as you would do in a normal object-oriented language.  (It's actually more complicated that this, as the pointer to the record contains several other pointers that point to the sub-objects within the record, and each of these need to be cast to the correct type before consumption as well, etc.)  Unfortunatley during the design of this .dll, it was assumed LabVIEW would be able to access the structure in the normal C++ way, so this is what I have to work with.

Having admitted my lack of comprehension, I will now take a stab and what your problem might be. Perhaps you are trying to cast the pointer and then use it as a C++ object pointer and access member functions or properties? If that is the case, then what you are trying to do requires a C interface DLL wrapper. LabVIEW can't use thiscall calling conventions that would be necessary to directly access the members of the object.

Well, I think you understand what I am trying to do, and are probably right that some helper-layer is going to need to be written.  Being the sole LabVIEW developer teamed with 40+ C++/.NET developers, I am constantly in the why-can't-LabVIEW-do-that discussions, so if it can be done in LabVIEW it is just easier to do it in LabVIEW than spending half the afternoon with the developers and the project architect discussing it.

Message Edited by Joe Gerhardstein on 08-05-2005 08:15 AM

Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 7 of 22
(9,787 Views)

Hi,

Like Paul, this topic also interests me. Here I'll tell about an experiences, hoping that it can bring just an idea.

in one of my last projects, I was using a DLL to capture the data from a miniPLC by using RS232 port. There were some objects like Digital inputs, digital outputs, analog inputs and outputs, function blocks status and etc that I used to read their data cyclically. there was a function in the DLL callled Read_Object and its prototype looked like this:

long Read_Object(unsigned char net_id, unsigned char object, unsigned short int index, unsigned char *data);

See the last parameter in line "data". it seems that "data" is a pointer to a byte. but it was the pointer to the first byte of an array which had different lengths for different objects. I think your problem is something like this. you have a pointer to a point of the memory, but this is the beginning point where a complex data srtucture lies. Is it not possible to feed an array of bytes (with definite length) to the DLL and then interpret the filled array after it has been processed by that DLL? I think there are two major problems with this idea.

1- the whole data will be copied once again in another place in the memory (I am pointing to initialized byte array)

2- interpreting the byte array to our complex data structure may be so difficult.

 

I hope it can be useful.

I've learned something new in this topic till now. hhmmm, Enjoying!

Message 8 of 22
(8,294 Views)
Well, I guess I have gotten so used to undocument stuff that I forget that LabVIEW actually has pretty good documentation with it.  On page 2-19 of the "Using External Code in LabVIEW" (see your LabVIEW Bookshelf), "Some APIs have structures and, in the case of C++, class data types.  LabVIEW cannot use these data types."

Thanks for everyone's input.  Sorry to send us all on a wild goose chase!
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
0 Kudos
Message 9 of 22
(9,774 Views)
Souresh:

Looks like we are trying to do the same thing, except as you mentioned, my pointer is to a complex data type that includes some pointers to other complex data types, which probably include pointers to other complex data types, etc.

Using my limited understanding of C++, I'll try to answer your questions:

1- the whole data will be copied once again in another place in the memory (I am pointing to initialized byte array)

In C, I believe you can simply operate on the data in it's original location (as referenced by the pointer), then put the results into another structure or back in the original location.  If you are trying to move the data from C into LabVIEW (or the other way), you are going to have to make a full copy as LabVIEW has it's own internal data model to hold the data it is using, and this can only be shared with C in a limited sense (specifically, LabVIEW must allocate the array and C cannot change the size).  So if you could find a way for LabVIEW to generate an empty array, then pass this array as a pointer to your "Read_Object" function and have "Read_Object" write the results directly to LabVIEW, you could end up with only 1 copy.  If "Read_Object" is creating the pointer, then you need to write a function in C that copies the data from this pointer into LabVIEW, you are going to end up with two copies (one in C, one in LabVIEW).

2 - interpreting the byte array to our complex data structure may be so difficult.

Very true.  Once you get away from primitive data types (string, integer, float) and into clusters, you are heading down a dark corridor to find a matching structure in C that can directly take your LabVIEW structure.  Same is true the other way around (complex structure in C getting into LabVIEW).  Your best bet is to break that complex structure up into primitives or arrays of primitives and pass them individually.

Interesting thread.  I believe we are exploring a gray area that is at the edge of what LabVIEW can do.  From what I have seen with .NET and LabVIEW, our capabilities should be signifincalty expanded as more driver code gets ported/written in .NET.
Joe Gerhardstein
Viasat
Certified LabVIEW Architect
Certified TestStand Developer
Certified Professional Instructor
http://www.viasat.com
Message 10 of 22
(8,284 Views)