LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Passing a Void pointer to a DLL in Labview

Solved!
Go to solution

I have a DLL supplied by a hardware manufacture that I am trying to run in Labview 2012.  The first function gets a handle to a device connected to the USB port.
PDEC i1d3Status_t i1d3GetDeviceHandle(unsigned int whichDevice, i1d3Handle *devHndl);  
i1d3Status_t is an ENUM of error codes and i1d3Handle is defined as void* i1d3Handle.
I wrote a wrapper for that DLL

int GetDeviceHandle(int device, i1d3Handle &handle) {
    i1d3Status_t m_err;
    int error;
    m_err = i1d3GetDeviceHandle(device, &handle);
    error = m_err;
    return error;
}

I can get this to work by passing the handle as adapt to type and handle by value.  The next function opens the device

int OpenProbe(i1d3Handle handle) {
    i1d3Status_t m_err;
    int error;
    unsigned char ucOEM[] = {0xD4,0x9F,0xD4,0xA4,0x59,0x7E,0x35,0xCF,0};
    m_err = i1d3OverrideDeviceDefaults(0,0,ucOEM );
    if(m_err == i1d3Success) {
        m_err = i1d3DeviceOpen(handle);
        if (m_err != i1d3Success) {
            unsigned char ucNull [] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0};
            i1d3OverrideDeviceDefaults(0,0,ucNull);
            m_err = i1d3DeviceOpen (handle);
        }
    }
    error = m_err;
    return error;
}

This works by passing the value of the returned handle from the previous VI as an I64.  There are several other functions that read parameter of the device so that I know it is open and the handle is valid but here is my problem.  The next function I have to pass it a pointer here is the code.

int GetDiffuserPosition(i1d3Handle handle, unsigned char* pos) {
    i1d3Status_t m_err;
    int error;
    m_err = i1d3ReadDiffuserPosition((i1d3Handle)handle, &pos);
    return error;
}

This code works in VC++ but not in Labview I get an 1097 error from the VI.  So passing the handle as a I64 will work as long as I don't pass another pointer along with it because this code will work.

unsigned char GetDiffuserPosition(i1d3Handle handle) {
    i1d3Status_t m_err;
    unsigned char pos;
    m_err = i1d3ReadDiffuserPosition((i1d3Handle)handle, &pos);
    return pos;
}

I even tried to dumb down the function

 

int GetDiffuserPosition(i1d3Handle handle, int* x) {

    *x = 5;

    return 0;

}

and still get the 1097 error.  Any suggestions would be welcome

0 Kudos
Message 1 of 9
(5,787 Views)

No need to make this so complicated. You don't need the wrappers around the DLL functions. Configure the device parameter as a pointer-sized integer passed by pointer. If you look at the help you'll see that this is effectively what you're doing already, since when you configure a Call Library Function Node parameter as Adapt to Type with a scalar input, the scalar is passed by reference and the Data Format parameter is ignored. In all the following functions, pass that same value as a pointer-sized integer passed by value, as you're already doing.

 

The problem most likely with the pos parameter is that you are not allocating it beforehand. Can you show your LabVIEW code, and the configuration of the call library function node? If "pos" is a string, then you need to preallocate it before passing it to the function. Generally the easiest way to do this is to initialize an array of U8, then use byte array to string (or, just pass the pos parameter as a byte array). Make sure you allocate enough space to meet the requirements of the DLL. In the "dumbed down" version, did you pass the integer parameter "x" by pointer?

0 Kudos
Message 2 of 9
(5,764 Views)

I had to write the wrapper because since the original DLL returned the error as an enum the Labview call would always return a 0 so I have to convert the i1d3Status_t variable to a int and return that from my wrapper DLL.  It seemed the problem was that Labview could not process the i1d3Handle varible which was difined as a void* when it was passed with another pionter.  So I could get the handle by using the adapt to type option and in the following calls pass the handle by value as a U64.  Labveiw was okay with me passing a U64 with the same value as the i1d3Handle as long as I didn't pass another pointer with it, then I would get the 1097 error. I think I have the problem solved by changing the wrapper DLL to accept a long long instead of the handle and then casting it to a i1d3Handle within the DLL wrapper.

 

int GetDeviceHandle(int device, long long &handle) {
    i1d3Status_t m_err;                    //create error enum
    int error;

    i1d3Handle i1d3dev;                   //create device handle varible
    m_err = i1d3GetDeviceHandle(device, &i1d3dev);         //get the device handle from the other DLL funciton

    *handle = (long long) i1d3dev;     //cast the device handle to a U64 pointer
    error = m_err;                           //return the error
    return error;
}

for Labview call

return_value is int

parm1 u32 pass value

parm2 u64 pass pointer to value

 

int GetDiffuserPosition(long long handle, unsigned char* position) {
    i1d3Status_t m_err;                   //for error handling
    int error;

    i1d3Handle i1d3dev;                   //create device handle varible

    i1d3dev = (i1d3Handle) handle;   //cast the device handle with the long long handle

    unsigned char pos;                    //pos to be passed to the i1d3ReadDiffuserPosition function as a pointer
    m_err = i1d3ReadDiffuserPosition(i1d3dev, &pos);      //this function is in a different DLL

    *position = pos;                         //assign the value of the pos to position

    error = m_err;                            //cast the error as a int

    return error;
}

for Labview call

return_value is int

parm1 u64 pass value

parm2 u8 pass pointer to value

 

This seems to work so I will probably go with it.

0 Kudos
Message 3 of 9
(5,736 Views)

Are you sure you aren't doing something simple wrong, for example configuring the Call Library Function Node with the wrong calling convention? I wonder if your DLL is simply translating calling conventions for you.

 

When you didn't use the wrapper, and did not receive a correct return value from the enumeration, how did you configure the return value? What size integer? Did you experiment with multiple options?

 

There is definitely no problem with passing multiple pointer parameters to a function - as far as LabVIEW is concerned, they're all just numbers. I can't figure out what you're doing wrong from your comments, but if you attach your LabVIEW code and the header file with the function prototypes, I'll take a look

0 Kudos
Message 4 of 9
(5,727 Views)

I have attached header file for the DLL. I also have attached a CPP file for a console program. 

As far as the labview code I am simply trying to create a library in labview for the fuctions in the DLL so they were just the the Library call with error checking.  Basically a Error In control to a case structure to check for an error in, the library call with the error going to a sub VI that updates the errror out with the code and text for the failure.  

The error returned from the function is 0 for success or either a postive number less than 100 or a negative greater than -1000 therefore it has to be a signed integer. 

At this point since I have gotten the functions to work with my wrappers I probably am not going to spend a lot of time on getting the supplied DLL to work by itself, but thanks for your help.

0 Kudos
Message 5 of 9
(5,713 Views)
Solution
Accepted by topic author lkprather

This snippet should be the correct Call Library Function Node for the Initialize and Read Diffuser functions. Give it a try? (If you're not familiar with snippets: this image is code. Drag it to your desktop to save a copy, then drag it into a block diagram. You'll need to fix the path to the DLL of course.)

CLFN Configured.png

 

0 Kudos
Message 6 of 9
(5,707 Views)

From a brief look at the header file, I think this might not work as intended as there is also a i1d3DeviceOpen() function that probably needs to be called before one can use other functions on that handle?

Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 9
(5,686 Views)

It works but I am now confused as to why mine didn't work it is pretty much the way I had it except I configured the path in the call but that shouldn't make a difference.  I don't have the VI I started with since I have made changes.  The only thing I may have had different is that in the getDeviceHandle I think I had the handle param set to adapt to type then wired to a I64 constant, but I tried this and it still works.  Oh well got lots of practice writing DLL's though.  How did you create that snippet?  Do you drag the code into a picture editor and save as a png file?

0 Kudos
Message 8 of 9
(5,673 Views)

@lkprather wrote:

[...]  How did you create that snippet?  Do you drag the code into a picture editor and save as a png file?


Just select the code you want to have in the snippet and select Edit >> Create VI Snippet from Selection.

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 9 of 9
(5,667 Views)