From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, 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: 

Should I throw exceptions from C++ DLLs for CLFN?

Solved!
Go to solution

I'm in the process of writing a C++ wrapper for a C library to use with LabVIEW's Call Library Function Node. The rational here is that the C library has a bunch of unfriendly structs and so perhaps a wrapper will simplify the calling code.

 

I'm wondering if I'm best served by returning error values or throwing exceptions when I have a problem in the wrapper/library. LabVIEW will give me error 1097 from the CLFN if an exception is thrown, but the message complains about memory corruption - does this depends on the code that throws?

 

For example, I could write the following:

int testFunction() {
    // Error!
    return 102;
}

and then check the return value, or I can write

#include <stdexcept>
void testFunction2() {
    // Error!
    throw std::runtime_error("Some error occured");
}

which should give me an error 1097.

 

Is this a valid way to write a DLL, or should I prefer parsing of return value ints, even though sometimes I might want a real return value, for example in

double GetSomeValue(unsigned short *handle, int address, int blahblahblah) {
    // Do some calculations, set up structures
    int returnValue = frustratingFunction(handle, address, length, weirdStructure);
    if (returnValue) {
        // Error occured
        throw std::runtime_error(getMessageFromCode(returnValue));
    }
    return parsedResultFromWeirdStructure;
}

Advice or pointers to things I really shouldn't do (or even consider) are greatly appreciated.


GCentral
0 Kudos
Message 1 of 3
(3,188 Views)
Solution
Accepted by topic author cbutcher

The exception handler that LabVIEW wraps around the Call Library Node (if you don't disable debugging completely in the Call Library Node) is a catch all exception handler that returns the 1097 error. Nothing specific about the exception is passed up to you calling hierarchy, so yes it will simply say error 1097 has occurred and most likely your memory layout is hosed and you should better restart your application or LabVIEW. This is because the most common exception that get caught with this are General Protection Errors and friends that result from accessing invalid or corrupted memory locations.

Exceptions are great if the entire calling chain is aware about them. This makes them really only fully usable if you stay in C++ or any other specific environment that supports it's own kind of exceptions (like Java for instance). Once you cross boundaries, even between different C++ compilers, you get into all kinds of nasty problems to pass meaningful exception information across those boundaries. Each compiler has its own specific exception mechanisme, protected by all kind of patents in the past. Most of those patents have probably expired by now, but the legacy they caused is still pretty dominant. The exception handling LabVIEW hooks into, is not really on the C++ exception handling level but a lower OS exception handling level. Microsoft C++ compilers do provide some bridging between the two, but with other compilers it may not even work with the Windows exception handling that LabVIEW uses to wrap Call Library Node calls.

 

So with all that in mind, I think it is a pretty bad idea to rely on the Call Library Node exception handling to pass error information to the caller. The only thing that will most likely happen if you ever intend to distribute that software as a library, is that there will be all kind of bad reports here in the fora and elsewhere about your library causing memory corruptions and that by disabling the debug level in the CLN configuration one can get it to work anyways. Which I feel is the same as removing your car breaks because they make some bad noise. 

 

Rolf Kalbermatter
My Blog
Message 2 of 3
(3,148 Views)

The error message about memory corruption is just LV's build in exception handling. If you know what's happening, feel free to ignore the corruption dialog. It's just an indication that control was lost and things might be bad.

 

Try setting the error handling in the CLFN to maximum. Then the error will (hopefully) be returned as an error out of the CLFN, and the dialog will disappear.

 

Usually (Windows API's) the return value is used (either 0 is no error, or 0 is no success). Might be worth to consider, it's a proven construct.

 

C++ DLL are usually more difficult to interface with, except when an effort (EXTERNAL keywords IIRC)  is made to be C compatible. C++ API by default use name mangling to specify OO stuff in the naming of the function. This is useful when the DLL is used with the same (version of) compiler, but useless if it's not.

0 Kudos
Message 3 of 3
(3,143 Views)