Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/21/2013 in all areas

  1. So this was a really fun one to debug. Background: this is my first actor framework project and I was having an issue where some of my messages would crash the LabVIEW IDE with an access violation. Four hours and several red herrings later, I present to you the offending code: This is a simple Enqueue Message VI created by the stock Actor Framework Message Maker in LabVIEW 2012, and as far as I can tell has never seen any manual edits. I mean seriously-- if I had ever touched it no way the diagram would be that messy! The VI shouldn't be foreign to anyone who works with the AF except look carefully at the "DevCmd" (Device Command) object on the block diagram. Somehow that constant has a non-default value. Which is really interesting because the class in question contains an empty private data cluster and it always has. I don't believe the Device Command class has seen any edits either, in fact the class is essentially an interface as it has no state data and only defines a single dynamic dispatch method which is a no-op. Classes derived from Device Command define state and behavior appropriate to whatever that particular command is trying to do. I have no idea what kind of non-default data might be in an empty object, but there you have it. Anyways, that message is used a lot in my application as ultimately the Actor method invoked by the Message's Do.vi forwards the Device Command to an asynchronous non-Actor task, and there are several specific Device Command implementations. Sure enough, any Device Command I tried to send would crash out with the access violation because of that Send Message VI. Other interesting things included if I made a selection on the block diagram including the offending constant, I couldn't execute cut/copy commands. Couldn't create VI snippets either. Anyways, deleting the constant and replacing it solved everything: I still have no idea how that VI got the way it was. One possibility is the Device Command class is private. I'm wondering if the message maker gets tripped up by this? When the message was originally created, the class was broken until I pulled the message class into scope of the containing library. Perhaps I should have checked the block diagrams?
    2 points
  2. I finally convinced Bossman we should move to making 64-bit exectuables, since most of our analysts use 64-bit machines. And it's a pain developing on a 64-bit machine, porting all the code to a 32-bit machine, recompiling, rebuilding, making an installation, blah, blah, blah. So I make my first real 64-bit build, put all my exes into an installer, and... it doesn't run. Specifically anything that is calling NI_AALPro.lvlib doesn't run. It seems to be missing. When it's run from dynamic code, the code just gets the "Code error" message and doesn't run. When it's called normally, the exe throws lots of errors on startup like: "An error occurred loading NI_AALPro.lvib: Unwrap Phase.vi LabVIEW load code error 3: Could not open front panel." (not really sure why this is an error, since Unwrap Phase isn't supposed to have an open front panel) And when the front panel of the exe opens (with a broken error, of course) there's a long list of NI_AALPro.lvib vis that are missing. Ironically, the exact same build/installer parameters (as far as I can tell) work fine when done on a 32-bit machine. Sigh. mje in this thread said he had to install the runtime separately to make his installation work correctly. I tried this, and the exes are now running correctly. But this is not a good long term solution as these applications need to be installed on a few dozen computers, many of which I will not have access to until right before the next test. And Bossman isn't very happy with me... Any idea what I might be doing wrong?
    1 point
  3. I don't have a recommendation for your specific issue, but if you just select all the additional installers does everything work? How about if you manually install the full runtime engine yourself? I ran into a similar issue with the 64 bit IDE where the installer it created was missing some critical component that broke my executable. After contacting an application engineer at NI the only solution was to use a third party installer which installs the the entire runtime as there was no way to configure the IDE to include the component- you might have to do the same, or alternatively instruct users to install the full RTE themselves. I should add that if you can narrow down what's going on, please contact NI so they can log the issue and address it in future releases.
    1 point
  4. If you distribute code with the diagram removed, you're locking the users into that version of LabVIEW. I don't think I'd buy a toolkit that I couldn't use with a newer version of LabVIEW, or couldn't move to a different LabVIEW platform than the one for which it was compiled. At the very least that would be a significant limitation. If the password protection makes it possible for companies to sell toolkits and be comfortable that their IP is sufficiently secure without removing the block diagrams, I'm fine with it.
    1 point
  5. You asked for it. A little cleaning went a long way, just did not have a chance to document things very well (have to jog my memory for that). This was built with piecemeal documentation, mostly to the original iso-spec, and with a lot of reverse engineering. Seems to work as well as my iPhone reader, hard to tell which one is the problem in a few corner cases. Not sure if I want to be on the hook for documentation/support if I posted to the CR, maybe a NI community page is in order, or Mr Mike will sort his out and add to the page. By all means let me know of any bugs, certainly a lot of version/EC combinations have not been tried. QR Generator.llb
    1 point
  6. Rolf's suggestion is not the best way to do this. You actually can directly pass an array of clusters to C code and treat them as C structs, and you can even modify and resize that array. Here's how: Configure your call library node parameter as "Adapt to Type", and make sure that you have "Handles by Value" selected for the Data Format. Once that's done, wire up your array of clusters (if you start with an empty array, just create an empty array constant with the right type and wire that). Now, right-click on the call library node and choose "Create .c file...". That will generate a file containing C code with the proper C types for your array of clusters and the right function prototype. It will look something like this: /* Call Library source file */ #include "extcode.h" /* Typedefs */ typedef struct { int32_t Element; } TD2; typedef struct { int32_t dimSize; TD2 Cluster[1]; } TD1; typedef TD1 **TD1Hdl; void funcName(TD1Hdl arg1); void funcName(TD1Hdl arg1) { /* Insert code here */ } Obviously we don't do a good job of naming these types, so you should rename them first (ex: replace TD1 with MyArray and TD2 with MyStruct). Important: On 32-bit Windows you need to do one more thing to this code to make it work right in every case. Modify it like so: /* Call Library source file */ #include "extcode.h" /* Typedefs */ #if MSWin && ProcessorType != kX64 #pragma pack(push,1) #endif typedef struct { int32_t Element; } MyCluster; typedef struct { int32_t dimSize; MyCluster Cluster[1]; } MyArray; typedef MyArray **MyArrayHdl; #if MSWin && ProcessorType != kX64 #pragma pack(pop) #endif void funcName(MyArrayHdl arg1); void funcName(MyArrayHdl arg1) { /* Insert code here */ } The #if/endif and #pragma lines are the ones you need to add. This fixes alignment on 32-bit Windows because LabVIEW on that platform does not use the default alignment. If you don't do this then the C code will not interpret the data correctly in some cases. With that done, you just have to implement your code. Note that the function takes a MyArrayHdl (aka, a MyArray**). This is a "handle" to a LabVIEW array. LabVIEW arrays internally are structures containing an int32 dimension size (for each dimension) followed by an inline array of the elements. So, for instance, to sum all the elements in the example above you would write code like this: int32_t sum = 0; if(arg1) // empty arrays will have a NULL handle { for(int32_t i = 0; i < (*arg1)->dimSize; ++i) { sum += (*arg1)->Cluster[i].Element; } } That's all it takes to just read or modify the existing elements of the array of clusters. What about resizing? That's a bit trickier, but it's still possible. To resize the array you need to resize the handle, update the dimSize, and initialize any new elements (if you grew the array). When you resize the handle you have to calculate the size of the whole array in bytes. Here's the correct way to grow the array above by one element: MgErr err = mgNoErr; if( mgNoErr == (err = DSSetHSzClr(arg1, Offset(MyArray, Cluster) + sizeof(MyCluster)*numElems)) ) { (*arg1)->dimSize = numElements; // Initialize new elements } else { // error (probably mFullErr) } If you allow for an empty array to be passed in then you might get a NULL handle, which you can't resize. To allow for that, change your call library node by setting the Data Format of that parameter to "Pointers to Handles". This will change the type from MyArrayHdl to MyArrayHdl* (aka MyArray***). You would then work with it like this: MgErr err = mgNoErr; size_t arraySizeInBytes = Offset(MyArray, Cluster) + sizeof(MyCluster)*numElems; if(NULL != *arg1) { err = DSSetHSzClr(arg1, arraySizeInBytes); } else // empty array, must allocate { if( NULL != ( *arg1 = (MyArrayHdl)DSNewHClr(arraySizeInBytes) ) ) err = mFullErr; } if(mNoErr == err) { (**arg1)->dimSize = numElems; // Initialize new elements } else { // handle error } The last thing you have to do is to link your DLL to labviewv.lib (in the cintools directory of your LabVIEW installation, along with extcode.h). This gives you access to the DS* functions (and all the other functions in extcode.h). Make sure you use the labviewv.lib version. That's the one that's smart enough to make sure that it uses the correct versions of those functions even if you have multiple LabVIEW runtimes loaded in the same process. Now, obviously a lot of this is a bit tedious (much harder than using a simple C-style array), but it's not actually very difficult once you know how to do it. Don't be afraid to try it. It's easier than it looks, and it can make your LabVIEW/C interactions much more flexible.
    1 point
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.