Jump to content

Rolf Kalbermatter

Members
  • Posts

    3,783
  • Joined

  • Last visited

  • Days Won

    243

Everything posted by Rolf Kalbermatter

  1. crossrulz is very correct. VISA only supports TCP/IP and that in two flavors. The first with the ::INSTR postfix is according to the VXI-11 standard that provides a resource discovery service (ala Bonjour) on the device that allows NI Max to query for connected devices and query their specific settings. The second variant uses the ::SOCKET postfix and is raw TCP/IP communication. The resource specifier needs in that case also a port number in addition to the IPv4 device address. UDP communication in LabVIEW is only possible with the UDP native nodes in LabVIEW. No NI-MAX will be getting harmed nor in any other way getting involved in this!
  2. Those handle functions only really worked on the Mac, since they were actually creating native MacOS handles, not the LabVIEW own flavor of them that was a sugar layer around the rather arcane Macintosh memory manager calls. Yes the Macintosh memory manager was famous for being not high performant and quite crash sensitive. It worked for most Macintosh applications sort of, but LabVIEW really was considered a stress test for it. It was also regularly stressing the Macintosh Programmer Workshop C compiler that the LabVIEW team used to build the product. It was quite a regular happening that NI had to request Apple support to build a new version of it with bigger symbol table space, in order for the compiler not to fatally crash during build of some of the larger C source files. When the multiplatform version was started some of the real cracks in the LabVIEW team actually prefered to develop and debug on the Sun Solaris version of LabVIEW, since the compiler and debugger tools where a lot more powerful on there, even though everything was in fact all command line based. And yes LabVIEW 2.5.x was Windows 3.1 only. It was never tested nor build to run under Windows 95 or later, which would have been very difficult considering that it was released in fall 1992. The first version supporting Windows 95 natively was AFAIK LabVIEW 4.0. LabVIEW 3.1 or thereabout did however have a version that could be installed on Windows NT 3.1.
  3. I used to have a whole box of disks and CD ROMs of old versions, though nothing before 2.2.1 which was Mac Only. But after 30 years and 3 major relocations, almost all of this has eventually ended up in the big round archive called trash bin. It's just not practical to hold onto these forever, and that stuff actually weights quite a bit altogether. Not fun to carry around and also not fun to fill up storage space (that I seem to always have not enough).
  4. Why do you think you need to downgrade NI-VISA? Does something not work? Have you tried anything? While you indeed usually need to have a NI driver version that is not more than 3 years higher than the LabVIEW IDE you are using, that is somewhat less of a program for NI-VISA. First most NI VISA functionality in LabVIEW is built in, so there are not a lot of VIs that an NI VISA installer could add to your LabVIEW installation. Maybe the example VIs, but I'm not even sure about that. Second, the NI-VISA API itself has been very stable over many years and there is little reason to believe that you would run into compatibility issues with a bigger version difference. Basically on the development system where you run the LabVIEW IDE, you should make sure that the versions do not differ to much, but on remote systems where you only intend to execute built applications, almost every version of VISA would work, but it is always a good idea to use at least the same version or newer as you used to develop/built your program.
  5. Post your LabVIEW project for the DLL, the DLL and its header. And please do a save for previous for2020 or earlier.
  6. It looks fairly ok. But you have a problem. You need to free that handle and that is not trivial. You need to call DSDisposeHdl() from the LabVIEW manager functions, however it depends on various things as to what DLL that function needs to come from. Most likely however does your DLL already export a helper function. Have you checked the header for your DLL? Isn’t there an additional function named DisposeLStr or similar exported? Calling that correctly will properly deallocate the handle after you are done with it. One small correction, COM either means a serial communication port or the underlying technology for ActiveX (Component Object Model). There is a separate Python module to handle COM interfaces but that works differently. Here you simply call classic DLL functions.
  7. The closest in terms of no runtime cost would be Conditional Compile for CPU architecture: anything but x86, x64, arm32 and arm64 is Big Endian. Alternative would be to check the VI Server property for CPU type. My version of runtime check used to be to use MoveBlock to copy a two character string with different ASCII characters “BE” into an int16 and check its value to be equal to 0x4245
  8. I always use Unflatten from String/Flatten to String. It even has a third Endianess selection to never byte swap. It may be not as fast as MoveBlock but has been fast enough so far for me. The only thing I don’t like about it is that it forces String on the flattened side but a Byte Array to String or String to Byte Array solves this. It would be trivial for the LabVIEW devs to allow Byte Array too, just a flag in the node properties that would need to change and should have been done so 20 years ago and set as default as a first step to allow the divorce of String==Byte Array assumption that still hampers proper adoption of non ASCII strings in LabVIEW. I even hacked a LabVIEW copy in the past to allow automatic adaption of the Unflatten from String Node to Byte Arrays but that was of course a completely undistributable hack. An according LabVIEW Idea Exchange suggestion from me was acknowledged by AQ himself but dismissed as highly unlikely to be implemented by LabVIEW R&D. https://forums.ni.com/t5/LabVIEW-Idea-Exchange/Allow-Unflatten-from-String-to-also-accept-an-Unsigned-Byte/idi-p/3968413
  9. For anyone looking at this library, I did an update in LabVIEW 2009 to properly support both 32-bit and 64-bit LabVIEW without any potential trouble. https://forums.ni.com/t5/LabVIEW/LV-slows-down-extremely-when-having-large-contents-in-clipboard/m-p/4251413
  10. What is a panther programmer? How do you interface to it? Your problem description sounds mostly like a basic LabVIEW programmer problem. Have you done some online programming courses and tutorials? Do you know how to write a simple LabVIEW program?
  11. It may be the printer or its printer driver.
  12. Actually, there is no direct way to call it that I would know of, but it should be possible to send the according menu command to LabVIEW. But what do you want to do then? This is not a vi, but an internal LabVIEW dialog. It does use a front panel resource like what VIs use but it is not a VI, the entire programmatic handling is a C code function.
  13. Please, follow a C programming course first and work through it until you get to the advanced topics including memory pointers! This is not LabVIEW but C programming. You are missing very fundamental pointer knowledge! testDataBlock.DataRecords = (DataArrayHdl)handle; Alternatively you can write the code directly like this. size_t len = offsetof(DataArrayRec, elms) + size * sizeof(DataRecord) if (!testDataBlock.dataRecords) { testDataBlock.dataRecords = (DataArrayHdl)DSNewHandle(len); if (!testDataBlock.dataRecords) err = mFullErr; } else { err = DSSetHandleSize((UHandle)testDataBlock.dataRecords, len); } And you need to do that every time again. testDataBlock is on the stack, this stack gets invalidated every time you leave your function. That is why we do a DSDisposeHandle() before leaving the function, to deallocate the previously allocated handle before the stack is invalidated and the handle lost forever.
  14. I added my comments in the comments behind //// static MgErr PostDataMessage(LVUserEventRef rwer, int32_t adapterNr, DataRecord *dataPtr, int32_t numElements) { // when you create the variable "testDataBlock" everything in the block is made 0 with the use of {0} // dataRecords points to a memory location which has got an unknow size. At this time the pointer is a Null pointer maybe ? //// => wrong!! It is a NULL pointer so it is not an unknown size but an invalid pointer pointing nowhere! DataBlock testDataBlock = {0}; // Here you use the function "NumericArrayResize" to resize the memorylocation dataRecords points to //// yes, it is a LabVIEW handle and needs to be accordingly setup, but since it is never really passed to the LabVIEW diagram //// it would not strictly be necessary to allocate it as LabVIEW handle but it needs to have the exact memory layout so it is //// easiest to do that in this way, anything else is going to confuse you simply more!!!! MgErr err = NumericArrayResize(uL, 1, (UHandle*)&testDataBlock.dataRecords, 2 * numElements); if (!err) { testDataBlock.adapterNr = adapterNr; // Here you use MoveBlock to Move the data from the source location where dataPtr points, to the // correct location of testDataBlock. You use the (*(..)) because if you would have used // *testDataBlock.dataRecords->elms you did point at the beginning of testDataBlock and not to the begining of elms //// wrong!! It is simply for correct C operator precedence evaluation, -> has higher precedence and would be evaluated //// before the * (pointer dereference) operator and would give you a compiler error since testDataBlock.dataRecords //// has no elms member, but *testDataBlock.dataRecords has, and I prefer to use more brackets to make it simply more //// clear, so (*(testDataBlock.dataRecords)) but the inner brackets are not strictly needed as operator precedence //// rules work fine here (. structure access has higher precedence than * pointer dereference, just as we want it here) MoveBlock(dataPtr, (*(testDataBlock.dataRecords))->elms, numElements * sizof(DataRecord)); (*(testDataBlock.dataRecords))->dimSize = numElements; err = PostLVUserEvent(rwer, &testDataBlock); // (this was your comment): PostLVUserEvent does a deep copy so we need to deallocate this handle to avoid a memory leak //// right! the testDataBlock memory area is going away at exit of this function and the handle stored in too, so we need //// to deallocate it otherwise it is lost DSDisposeHandle(testDataBlock.dataRecords); } return err; } No no! Doing it yourself instead of letting LabVIEW do it is only making things only really worse. And you definitely and absolutely are doing the calculation wrong although it will be simply a to big allocation so at least you won't blow up your harddisk. 🙂 Something like this would be more accurate: size_t len = offsetof(DataArrayRec, elms) + size * sizeof(DataRecord) if (!handle) { handle = DSNewHandle(len); if (!handle) err = mFullErr; } else { err = DSSetHandleSize(handle, len); } Sorry mate, but this sounds gibberish and I have no idea what you mean.
  15. There are many ways you can print and it is not entirely clear to me which one you use. If you use the method to have LabVIEW send a front panel to the (default) printer, what really happens is rather involved. LabVIEW has no idea if the printer is a real printer, using EPS, LPD/LPR, JetDirect or whatever else underlaying printer driver protocol. All it knows is that the printer driver supports a GDI interface (The Windows Graphic Device Interface specification that is also used to draw items on the screen) and it pretty much treats it exactly the same aside from some extra setup steps such as page size and orientation. What finally ends up on the printer is very specific on the quality of the printer driver and its ability to render each of the zig hundred GDI commands properly in a resulting output. It seems that the PDF printer driver you are using, does some shortcuts by not rendering everything itself but for instance letting rotated text be rendered by the Windows GDI subsystem itself and then reading the resulting bitmap and adding that into the PDF stream. A very valid procedure although of course not the highest quality result. Other PDF printer drivers may be a bit more developed and translate this properly into direct PDF commands, but they may cost something.
  16. Unfortunately, the LabVIEW internal manager function that would return the list of enumerated fonts is not exported from the LabVIEW runtime. That would have been a lot easier and platform independent.
  17. Well, with that much information we can only tell you: Good luck! What interface? What part do you want to make read only? What platform? What LabVIEW version? Can you show in a simple VI what you try to do and what you have done so far? Up to now, you basically only said that you need help and nothing else. You need to be a lot more specific in what is your problem!
  18. Some Dynamic DNS or similar could help with the problem of a dynamic IP adres device in the field. It would require a fairly simple modification in the cRIO setup, but if you use an NI Linux RT type this should be pretty trivial. Of course you will need to have access to a Dynamic DNS service somehow, they are usually not for free. No-IP for instance provides a free version but requires you to manually confirm it every 30 days and does not support SSL certificates on that level. For 1.99 per month you do get SSL and a 1 host name resolution without monthly confirmation. Other services have similar offers. The free tier has usually several limitations that are inconvenient but not a huge problem for private deployments. But they pretty much won't work for a commercial deployment.
  19. No, no, no! #include "extcode.h" #include "lv_prolog.h" typedef struct { int32_t status; int32_t value; } DataRecord; typedef struct { int32_t dimSize; DataRecord elms[1]; } DataArrayRec, *DataArrayPtr, **DataArrayHdl; typedef struct { int32_t adapterNr; DataArrayHdl dataRecords; } DataBlock; #include "lv_epilog.h" static MgErr PostDataMessage(LVUserEventRef rwer, int32_t adapterNr, DataRecord *dataPtr, int32_t numElements) { DataBlock testDataBlock = {0}; MgErr err = NumericArrayResize(uL, 1, (UHandle*)&testDataBlock.dataRecords, 2 * numElements); if (!err) { testDataBlock.adapterNr = adapterNr; MoveBlock(dataPtr, (*(testDataBlock.dataRecords))->elms, numElements * sizof(DataRecord)); (*(testDataBlock.dataRecords))->dimSize = numElements; err = PostLVUserEvent(rwer, &testDataBlock); // PostLVUserEvent does a deep copy so we need to deallocate this handle to avoid a memory leak DSDisposeHandle(testDataBlock.dataRecords); } return err; } And yes, my order of the elements in DataBlock seems the other way around than yours, I did it according to the optical order in your image, as that was all I had to go by.
  20. The first step in trying to create a DLL that uses LabVIEW data types natively, is to configure a Call Library Node to have a parameter which is configured Adapt to Type. Then connect the datatype you want to use to this parameter, right click on the Call Library Node and select "Create .c file". The resulting C file has an exact C type declaration for the parameter. Copy paste and start programming your code you want in your own C file. #include "extcode.h" #include "lv_prolog.h" typedef struct { int32_t status; int32_t value; } DataRecord; typedef struct { int32_t dimSize; DataRecord elms[1]; } DataArrayRec, *DataArrayPtr, **DataArrayHdl; typedef struct { int32_t adapterNr; DataArrayHdl dataRecords; } DataBlock; #include "lv_epilog.h" This is what your type will probably look like. Obviously the int32_t is just a guess, can't see that from an image.
  21. Actually DSNewPtr is not really needed. You can very well provide the necessary memory space by a simple Initialize Array node, datatype U8, size 8 * 512 + 3 * 4 and pass that as C array pointer to the shared library. Then do some indexing into the resulting array after the function executed and some Unflattening for the 3 integers and all should be well.
  22. Your problem likely is that SVLibInit() opens a handle to your file(s) and you never release them. Windows (Linux too) will clean up unclosed handles/fileids when a process exits but not before that. So you should also have a function SVLibUninit() or similar that will then release all the resources, and of course call it from LabVIEW when you are done with your software. Once that happens, you can access those files from other processes too, without needing to close LabVIEW.
  23. It misses context. void means NOTHING, and void * means a pointer to whatever the C programmer may have decided. Problem is that if the caller and callee don't agree what that anything means, really BAD things will happen. But without some more information all I can say is that it is a pointer and that would be in the LabVIEW Call Library Node a pointer sized integer. If that could work in this context is at least questionably. There obviously would need to be some other function that can return such a "handle"to you. The functions as you show them only consume this handle and can't create it in a meaningful way.
  24. Not sure, but it should be very trivial to test. Just put a list control in one of the sub panels, add several few thousend items to it and loop through it to update the cell background. Observe if your list control updates quickly.
×
×
  • Create New...

Important Information

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