LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

c pointers/handles and LabView references

Programmers:

I'm opening up a database connection from my C-based DLL and have handles :
 #include <sql.h>
 #include <sqlext.h>
 HENV henv;  // ODBC environment
 HDBC hdbc;  // ODBC connection

If I return the handles back to LabView to use with other various queries and a close database function, can I use the LabView LVRefNum so that I can follow convention with a teal colored wire as a reference (and can be stored as a reference), or do I have to use a  unsigned long int to store the 32 bit pointer/handle?

   ...Dan
0 Kudos
Message 1 of 11
(4,621 Views)
I'm not positive, but I think you have to use U32 going into and returning from the DLL call.  You can then use Type Cast to change from the blue wire to the teal wire.
- tbob

Inventor of the WORM Global
Message 2 of 11
(4,620 Views)
Maybe I can use a type cast from C.  Does anyone know how to do this?

I tried looking for the definition of LVRefNum in extcode.h but it wasn't clear (too many MACRO defs).

   ...Dan
0 Kudos
Message 3 of 11
(4,608 Views)
U32 works well, as does the typecast to and from REFNUM.

I do wish someone from NI would explain LVRefNum.  The way I'm using it right now works well -- it'd be nice to understand more so that I won't have to worry about the reliability of the code (or how to switch to 64 bit).

   ...Dan
0 Kudos
Message 4 of 11
(4,585 Views)
Dan:

LVRefNums are unsigned long data type (32 bit). You can cast them in LabVIEW and then use them as parameters to call your DLLs.

Message 5 of 11
(4,566 Views)


@dgholstein wrote:
Maybe I can use a type cast from C.  Does anyone know how to do this?

I tried looking for the definition of LVRefNum in extcode.h but it wasn't clear (too many MACRO defs).

   ...Dan


LVRefNum is in principle a pointer to something as far as your DLL is concerned. And this something will be whatever the code implementing that object will want to do. For standard LabVIEW refnums only the internal code parts in LabVIEW implementing that object know how this something looks. All the rest of LabVIEW simply treats it as a pointer or in fact even more correctly as an uInt32. Since it really is a pointer once LabVIEW 64 bit is a reality such a refnum likely will be an uInt64 in that version.

The way I usually deal with my own refnums is by creating a structure that contains anything I need that is associated with that object and on passing back this "refnum", typecast a pointer to this structure to a LVRefNum (and on receiving such a refnum do the opposite). In order for my code to be able to assess that the passed refnum is really valid the first element in my structures is usually a magic 32bit integer that is checked to be this magic before attempting to do anything else with it when my code receives such a refnum from the LabVIEW diagram.

In LabVIEW I use a Datalog FileRefnum in which I have placed an enum with a specific single named item in it. This makes sure that as far as the LabVIEW diagram is concerned, it is a uniquely typed refnum and you can't accidentially connect different unrelated refnums together.

Rolf Kalbermatter

Message Edited by rolfk on 06-28-2006 07:31 AM

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 6 of 11
(4,564 Views)
Rolf;

I've successfully implemented this in my library and do the type cast in LabView, not in the DLL.  Do you type cast in LabView or the DLL (to LVRefNum).

The unique LVRefNum that can't be wired to a different type of data sounds good to me, do you have a quick example of how to do that?  Do you do that in C or in LabView?

   ...Dan
0 Kudos
Message 7 of 11
(4,554 Views)
This isn't directly related, but I do want to clarify something since refnums are used by several subsystems in LabVIEW.
 
In general, a refnum is an opaque pointer for LabVIEW. In other words, you can convert the refnum to and from an integer, but you can't create them nor can you use them yourself.
 
For example, let's say you open a handle (IUnknown*) to a COM object inside your DLL. You then convert the IUnknown* to an integer and then cast it in LV to an ActiveX refnum. If you attempt to use that refnum with the ActiveX palette in LV, you'll get an error back - the AX refnums in LV are not a direct translation of the IUnknown pointers, but a special index into a table within LabVIEW where we keep the pointers.
 
Similarly, if you open the AX component in LabVIEW and then try to cast it to a pointer in your DLL, you'll get garbage (and a crash in your DLL) since the refnum isn't a true pointer.
 
As I said, this isn't an issue for what dgholstein wants, since he's creating the handle outside LV and will only access it outside LV...but I've seen people try to do this with AX and .NET before, so I thought I'd bring it up.
Message 8 of 11
(4,546 Views)
Brian;

That is exactly what I wanted to know, namely, what exactly is LVRefNum and what are the restrictions.  Thanks.

   ...Dan
0 Kudos
Message 9 of 11
(4,537 Views)


@dgholstein wrote:
Rolf;

I've successfully implemented this in my library and do the type cast in LabView, not in the DLL.  Do you type cast in LabView or the DLL (to LVRefNum).

The unique LVRefNum that can't be wired to a different type of data sounds good to me, do you have a quick example of how to do that?  Do you do that in C or in LabView?

   ...Dan


I simply create a datalog refnum control, place an enum in it and set a single string item in that enum. Then you pass this to the Call Library Node configuring the according parameter to be passed as Adapt to Type. The parameter will then be passed to the DLL as LVRefNum *refnum (thus passed by reference).

Inside my C code I usually do something like this:

typedef struct {
    int32 magic;
    .......
} MyRefNumRec, *MyRefNumPtr;

MgErr MyFunctionCreate(LVRefNum *refnum, .......)
{
    MyRefnumPtr ptr;

    if (!refnum)
       return mgArgErr;
  
    ptr = (MyRefnumPtr) DSNewPtr(sizeof(MyRefNumRec));
    if (!ptr)
      return mFullErr;

    ptr->magic = kMyMagic;

    /* Do something more here */
   ..................

    *refnum = (LVRefNum*) ptr;
    return noErr;
}

MgErr MyFunctionOperate(LVRefNum *refnum, .......)
{
    MyRefnumPtr ptr;

    if (!refnum || !*refnum)
       return mgArgErr;

    ptr = (MyRefnumPtr)*refnum;
    if (ptr->magic != kMyMagic)
       return mgArgErr;

    /* do something useful here */
    ...............

    return noErr;
}

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 10 of 11
(4,526 Views)