-
Posts
3,871 -
Joined
-
Last visited
-
Days Won
262
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by Rolf Kalbermatter
-
Please not that this is not exactly a cheap way of determining an array size. The value extraction will create a copy of the array, potentially using quite some memory and also costing performance to do the copy. No problem if your array contains only a few 100 elements but definitely something to think of with an array that could contain 1 million values.
-
Well, it is unfortunate but not really a problem. If the VI needed recompiling at all, it already is recompiled when opening its reference and if it didn't need, well then why to try to force it anyways? Well and that is where you go wrong. What you propose is no different than removing the diagram code altogether. There LabVIEW can't recompile the diagram on load anymore since it isn;t there so loading a VI into a LabVIEW system that is not the same version or platform breaks the whole hierarchy. With password protection the diagram is still there and LabVIEW can access it for recompilation when necessary. It simply won't let anyone open the diagram to look at the code. Is it absolutely safe? Of course not, the only way to be 100% safe is not to distribute the diagram at all in any way and even better yet not distributing the VI at all since theoretically anyone with enough time at hand can go and try to find the compiled code, analyze that and reverse engineer the original diagram. The only safety here is that locating that compiled code and reverse engineering it is a lot more complicated and time consuming than doing the same with a normally compiled C/C++ program.
-
Check for data on TCP connection
Rolf Kalbermatter replied to mike5's topic in Remote Control, Monitoring and the Internet
No my library wouldn't really help with that although it could probably add such a poll feature somehow. The library really is meant to make use of SSL and other TCP/IP socket functionality almost as simply as the original TCP nodes do. For IPv6 that is already mostly there, ping also with the additional limit of the required administrative rights, that is basically impossible to avoid on most modern OSes. SSL is another issue. SSL supports a lot of different kinds of operations and parameters that all need to be somehow supported. However most of them are obscure, with no examples at all and often seldom used. So for the time being the library supports opening SSL sockets with default settings, but not yet custom certificates and other stuff such as authentication since that requires a way to enter parameters when creating the socket. I have some ideas how to allow doing that but that requires quite some infrastructure and then the chances that anybody is going to use it are still very small. My library doesn't currently support accessing native TCP refnums other than a somewhat hidden feature with separate Get and Set Attribute VIs that can access any of the supported socket attributes also on native TCP and UDP refnums. Unfortunately there is no way of supporting that through the publicly exposed property nodes itself but only through the special VIs, which is not as convenient as the property nodes. Just one more comment. The error handling with WSAGetLastError() is probably never gonna return a meaningful error. (WSA)GetLastError() retrieves a thread local storage value set previously by another function. That assumes that the previous function and GetLastError() are called in the same thread and without any other function in between that could set that value. Since the CLN's are set to execute in any thread this is absolutely impossible to guarantee and in my experience actually almost never happens either. Not even setting both CLNs to execute in the UI execution system would be able to guarantee proper operation, since theoretically there could still execute another call to an API that influences this value, between when LabVIEW calls the recv() function and when it eventually calls the WSAGetLastError(). The only way to guarantee that this is working properly is by locating both calls in an external call library in one single function and call that through a CLN. -
How to know the available function's parameter list?
Rolf Kalbermatter replied to Breakpoint's topic in Calling External Code
Ohh dear a sourceforge project! Well I simply assumed that someone resorting to API export applications for a DLL would certainly not do that for an open source library. Talk about hiring an expensive detective to find out about "secrets" that are in the public domain!!! -
Password protected VIs definitely get recompiled on load when they are not in the current LabVIEW version. I'm also not understanding why Open VI Reference should fail to return a VI reference for a password protected VI when you don't provide a password. The password really only is required to make the diagram visible, so the Open BD method and some other operations are all that should fail on such a VI reference, but not the Open VI Reference itself. Have you tried to play with the flags parameter to Open VI Reference? And jgcode can you enlighten me what would be the security issue with allowing to get a VI reference on a password protected VI and being able to execute the Compile method on that? I totally fail to see any security issue with that.
-
Filling a cluster with strings and arrays dynamically
Rolf Kalbermatter replied to jbone's topic in Calling External Code
Not being able to look into the XNode I can't really say much about it. But it most likely doesn't just call MoveBlock() only but probably does some other things too, that are not strictly necessary in all situations. Not knowing the exact circumstances it is called in it may do so just to error on the safe side. It's definitely more complex than just calling two LabVIEW manager functions, and possibly XNodes also are limited in the way they are executed. Wouldn't surprise me if XNodes always executed in the single threaded UI Execution system, and that could be a major performance killer. -
How to know the available function's parameter list?
Rolf Kalbermatter replied to Breakpoint's topic in Calling External Code
We can't help you with this. Without documentation for a particular function it's not possible to deduce its parameter list other than by trial and error and disassembling the function in question. Disassembling code is however in some jurisdiction a crime punishable to quite some extend, and it also doesn't guarantee that you find out everything about the possible parameters either. So go and find the creator of that component and get better documentation from them. Failing that, look for a different component that is better documented. Sorry for the sad news but that is how this works and I can't perform magic. -
Filling a cluster with strings and arrays dynamically
Rolf Kalbermatter replied to jbone's topic in Calling External Code
Well if you find a different way to determine the length of a null terminated C string you are definitely a lot smarter than all the C cracks who have worked on the various standard C runtime libraries when implementing strlen(). MoveBlock() operates on a byte array only. There is no way it can determine the length of the source buffer at all. While it could be a typical C string it does not know about that. It's simply a char[] buffer, but char in C does not mean null terminated string at all, it's just the name for a byte sized integer. If you know that you have a null terminated string buffer you could do something like this instead: LStrHandle target = NULL; int len = StrLen(buffer); MgErr err = NumericArrayResize(uB, 1, (UHandle)&target, len); MoveBlock(buffer, LStrBuf(*target), len); LStrLen(*target) = len; This is as fast as it gets and I'm sure the XNode adds some complications to it, since it works for different parameter types too. Another LabVIEW manager call that does this more or less in one call would be: LStrHandle target = DSNewHdlClr(4); LStrPrintf(target, "%s", buffer); Since this incures an extra call to the memory manager function DSSetHandleSize() inside LStrPrintf() it is likely slower than the previous solution. -
labview queue from native windows dll
Rolf Kalbermatter replied to Mark Zvilius's topic in Calling External Code
Well this may be redundantet but have you checked the calling convention? MSVC by default does compile to use cdecl convention, but can be configured to use another default calling configuration for a project. Since your function does not specify any calling convention it will be compiled into the default calling convention and the error you see often gets caused by wrong calling convention configuration. Basically it messes up your call stack and that is quite fatal eventhough LabVIEW tries to protect you from this with an exception handler. DSDisposeHandle() takes the handle directly so assuming your earlier code it should be DSDisposeHandle(*pBuf); since pBuf is a pointer to a handle. But you should of course only call DSDisposeHandle() when NumericArrayResize() was successful or otherwise you get another nasty error. It's simply the standard trouble about C programming and what I usually end up doing is a more or less deeply intended code where the according cleanup operations are done one level deeper than where the resource was created. Some people prefer to have some sort of goto fail; whenever an error occurred, but coming from a strict Pascal schooling I still find gotos one of the biggest evils in a programming language. (quickly followed by application global variables) -
Filling a cluster with strings and arrays dynamically
Rolf Kalbermatter replied to jbone's topic in Calling External Code
As ned has already explained quite clear you have to use LabVIEW memory manager functions if you want to hand data back to LabVIEW directly. The GetValueByPointer XNode is just a way to deal with native pointers, when you have no way or don't want to modify the DLL itself to deal with LabVIEW handles directly. What it does is copying the data in the pointer into a LabVIEW handle. And if you don't clean up that pointer yourself afterwards it will be leaked. Nothing LabVIEW can do about, since the DLL interface is simply a function interface with no defined conventions about how to allocate and manage memory across that boundery. DLL x could use a standard malloc function for that while DLL Y comes with its own memory manager implementation and LabVIEW has no way of knowing about this at all. Why LabVIEW uses handles? Because traditionally that was required on older platforms to have efficient variable sized memory structures (strings and arrays) and changing that now is no option at all. Even if it would use pointers the fact that the caller never can know what the callee used to create a particular memory block and vice versa, would still prevent fiddling with pointers created in the other component. -
labview queue from native windows dll
Rolf Kalbermatter replied to Mark Zvilius's topic in Calling External Code
What does fail and how? What do you specify as size? Instead of translating the return value of NumericArrayResize() into just a boolean you could much better return the error code directly. That might give you a bit more feedback to the cause of a possible error. And of course I hope you are not executing this test many times, because you leak the handle every time :-) This looks ok to me. Some minor remarks. The dummy numPixels would not be necessary since it contains the same value as the handle size itself. Instead you could define the event to be simply a byte array and just pass the handle to PostLVUserEvent(). I make it a habit to change the handle size after I have filled in the data into the handle. That may seem just cosmetics and as long as you have arrays of skalar values that is indeed so, but if you talk about arrays of strings or other handles then there is a subtle difference if your loop aborts prematurely because of an error. If you have set the size before it may indicate a larger array than the loop effectively filled in and that could cause LabVIEW to try to access those not yet initialized values, causing crashes or other nasty things. -
labview queue from native windows dll
Rolf Kalbermatter replied to Mark Zvilius's topic in Calling External Code
Well I can't tell you what is wrong except that what I have initially provided to you is for 99% certain more correct than what you have shown in the last sample code. No, there is no way to use LabVIEW manager calls in a non-LabVIEW process. How should that work? Someone has to provide the implementation of those functions and that is either LabVIEW.exe or lvrt.dll. However lvrt.dll is not a standalone executable but just the runtime engine for LabVIEW and needs a very specific way to be initialized in order to work properly. The only one who knows how this initialization has to be done are the programmers at NI, and it changes for sure with almost every version of LabVIEW. The knowledge about this is all stuffed into the little startup stub that the LabVIEW application builder will tag to your executable. This startup stub is specifically meant to initialize the process as GUI process so linking it to your console program is also not a real option. However your code seems to indicate that you have never ventured into source code level debugging. But that is certainly a much better way to debug external code than trying to send some debug print messages to the LabVIEW task and hoping to decipher from that what might be go wrong in the external code. -
labview queue from native windows dll
Rolf Kalbermatter replied to Mark Zvilius's topic in Calling External Code
Naming conventions on a multiplatform project are really difficult to do. Windows C programmers use completely different naming convention than Macintosh C programmers, and they are again very different from Unix C programmers. So which one is the right for LabVIEW? LabVIEW traditionally used the old Macintosh Classic naming conventions for most things in its underlying C code interface, which does not use the awful Hungarian notation of Windows and also not the everything_except_CONSTANT_NAMES is lowercase mode of Unix. Which one is better? Well I don't like both Hungarian notation as well as unix_all_is_lowercase(). -
labview queue from native windows dll
Rolf Kalbermatter replied to Mark Zvilius's topic in Calling External Code
If you thinker with the code during debugging you should make sure to revert such changes before claiming it doesn't work. The commented out call to MoveBlock() is clearly the one you want to have here once you have corrected the call to NumericArrayResize() to take the pBuf argument without pointer reference as it should. Then LStrLen() later on will be able to reference the length parameter of the buffer and not some random value in memory Yes pointer handling is not easy and advanced pointer handling as used by LabVIEW internally to allow decent performance even less. That is why we all program in LabVIEW after all, isn't it? -
labview queue from native windows dll
Rolf Kalbermatter replied to Mark Zvilius's topic in Calling External Code
Right! No! NumericArrayResize() does not update the length value in an array. Read the documentation about that function which states so explicitedly. One of the likely reasons for this is that you want to update the length usually after you have added the elements to the array and not before. Otherwise leaving the routine early because of an error or exception will leave uninitialized array elements in the buffer that according to the length parameter should be there. And LStrLen(ptr) is simply a macro and not a function. It translates to #define LStrLen(ptr) ((LStrPtr)(ptr))->len; so it can be used both as lvalue and rvalue in a statement. -
DLL, Call Library Function and IntanceDataPtr questions
Rolf Kalbermatter replied to jbone's topic in Calling External Code
The InstanceDataPtr is basically what the GetDSStorage() and SetDSStorage() functions provided for CINs. It is a pointer value LabVIEW maintains for each Call Library Node in a diagram and in the cases of reentrant VIs with Call Library Nodes for each instance of such a Call Library Node. Your DLL can specifiy the three Callback functions ( I still think the name callback function is a mistake for this functionality) that all accept a reference to this InstanceDataPtr. These three functions Reserve(), Unreserve(), Abort() correspond somewhat to the CIN functions CINInit(), CINDispose(),, and CINAbort(). Usually you would in Reserve() check if the InstanceDataPtr is NULL and create it then or reuse the non-null value. In Unreserve() you should deallocate any resources that you created for this InstanceDataPtr. In Abort() you could for instance cancel any pending IO or other operations associated with this InstanceDataPtr to prevent the threaded Resetting.... dialog when your DLL function hangs on a IO driver call. The actual function associated with the Call Library Node can be configured to have an extra InstanceDataPtr parameter that will be not visible as terminal on the diagram. LabVIEW will pass the data pointer instance stored for the current CLN instance to this parameter. Please note, this is strictly for managing a specific CLN instance. It is not meant to pass around as a token between different CLNs or even different instances of the same CLN in case that the CLN resides in a multiple instantiated reentrant VI. It seems what you want is more a kind of token or handle you can pass between different CLNs to identify some resource. This has to be done by your library for instance by creating a pointer where all the necessary information is stored. You can treat this as opaque value as far as LabVIEW is concerned. Basically you configure the according parameter to be a pointer sized integer and pass this "handle" around in LabVIEW like this between the different CLNs. If you need to access content inside this handle in a LabVIEW diagram your library should export corresponding accessor functions that you can import with CLNs. -
Well I didn't feel I had to defend myself, but wanted to explain the issues as they apply to other use cases too. The work on this library actually prompted me to write some articles about External Code use in LabVIEW on the Expression Flow blog, and touches all these issues and some more. Yes it supports any combination of memory and file based archive and archive content datastreams (and I'm fairly proud of that accomplishment). This means that both for compressing and uncompressing, the source and target can be any combination of memory or file based data stream. Accessing the memory stream of archive components was a requirement to allow copying password protected archives (for instance when adding a new component or removing an existing one). And no it doesn't compromise password protection since the entire encrypted stream is copied and to unpack it you still need to know the original password. You could easily create archives in that way that are hard to open in some normal unarchiving tools, since different internal components can end up having different passwords, but that is simply a usage problem, not a fundamental problem of the ZIP archive or its operation.
-
The intermediary DLL is not so much a seperate DLL as the combination of the original zlib source code with the additional zip support that is now official part of the contribution directory but used to be just an optional component by someone else, and on top of that some utility functions to help support with LabVIEW integration. I could have left that all in separate DLLs but since I had to modify some zlib header files anyhow (to make the functions cdecl instead of stdcall as they used to be in older versions on Windows, and later on to decorate the exported functions with my own prefix to workaround naming clashes in the cRIO systems with empty stubs included in the system image) I decided to derive from the concept of providing fully original DLLs. And since the entire build process already was required anyhow for the additional LabVIEW specific part it wasn't really much extra work. In fact it makes building the shared library easier and also the packaging and distribution since only one shared library is required. The drawback is that merging in new zlib/zip versions is a little bit more complicated but last time when I added the new zlib version to it, the actual merging was done in less than an hour since I still only have to manually check and adapt two of the header files.
-
I think the main reason SVN is used so often is because it is easy to setup and to use. And with many LabVIEW programmers doing small teams or even single user scenarios, and having to install the version control too themselves this is simply a huge incentive. It's not because SVN is superior to those other version control systems (it's definitely not) but simply because it is easy to use (and easy to use it wrong too). It's definitely better than no version control at all and for the little cost it has in getting it to work an ideal tool for many. It has limitations such as not really supporting branching and merging and I have run many times into situation when copying a controlled module to a different computer and making some modifications there (you can't usually install arbitrary software on a customer computer, and you also can't debug system hardware which needs some specific interface hardware from your own development computer) and afterwards trying to get this back into the controlled module on my system. Hg seems to support that much better, and while git on a command line is a nightmare to use, it certainly has very powerful features.
-
Well from the pic there is no obvious reason why it shouldn't work. But there is only so much a pic says. It tells us nothing about the actual Call Library Node configuration and even less about what the function expects to do with the buffer. This is however very crucial information. The problem you pose to us is a bit like presenting us a picture of a car in a seemingly perfect condition and asking us why the engine doesn't work. Is gas in the tank? Is the engine in there? You see?
-
Well changing only the offsets into 64 bit integers won't work. You also need to change the calls to use the 64 bit versions of the functions. If they simply changed the offsets to just support 64 bits, backwards compatibility would be broken. A 64 bit integer is passed to a function in two 32 Bit addresses on the stack so changing all 32 Bit offsets into 64 Bits only, it would seem strange that you could even run an entire chain of VIs as this mismatch should mess up the stack alignment. Although thinking about it, the functions are all cdecl and that means the caller cleans up the stack afterward so it may work ok anyhow, if there are no other parameters after the offset in the parameter list. Like all OpenG libraries it's all on SourceForge.
-
Actually 64Bit and support for >2GB ZIP archives are two distinct issue. I have in the current HEAD integrated a new version of zlib which would support 64Bit offsets internally which is what is required to support archives containing more than 2GB components. The same version also SHOULD be compilable as 64Bit code. While these two things happen to be incorporated in a working way in the current ZLIB library, they are not equivalent and even not really related. I have come across some snatch in compiling the LVZIP DLL for 64 Bit and haven't really spent much more time on this until now. Well I can compile the code but it crashes and since I don't have a 64 Bit system at hand with a compatible source level debugger and LabVIEW installation (they both also need to be 64Bits) I can't at the moment debug it. The code as it is in the repository would apart from that crash be fully 64 bit capable and should also be able to handle >2GB components although that is nothing I have ever tested nor have thought to test so far. So the OpenG library as it is in the repository SHOULD be able to handle >2GB files but that will also need re-factoring of some VIs to allow for 64 bit integers wherever offsets are passed to and from the DLL functions (those 64 bit capable functions have a special 64 postfix.
-
call library function node error 13
Rolf Kalbermatter replied to Rammer's topic in Calling External Code
One possible problem might be that the DLL is a 32bit DLL and you were using it in the 32 Bit version of LabVIEW and now have upgraded to LabVIEW 2010 64Bit. LabVIEW only can call DLLs compiled for the same environment as it is itself. If this is the case you have two options: 1) Install LabVIEW 2010 32Bit which will work fine on a 64 Bit Windows version 2) Recompile your DLL for Windows 64Bit (and review it for any bitness issues) This review would encompass things such as that the Call Library Node is configured right: Windows 64 bit uses obviously different pointer sizes which could be a problem if you have configured pointer parameters to be treated as integers, but using the new pointer sized integer type since LabVIEW 8.5 would then be the right thing instead of explicit 32 bit or 64 bit integers Also there is a difference in size between long: Windows treats longs always as 32 bit while everyone else treats a long as 32 bit on 32 bit platforms and 64 bit on 64 bit platforms. Use of long long instead in the C code avoids that problem as it is always 64 Bit but it is a C99 feature only so it may have problems with older compilers and also C++ compilers who don't support the upcoming C++0x standard not being able to recognize it. -
I fully agree! And for me VB always has been a nightmare to deal with. Apart of the syntax which I always found fuzzy and unclear (coming from Pascal and Modula which we learned in school) I HATED the separation of the code into separate methods for every event and what else. If I wanted to get an overview of a program I had to either print it out or click through many methods to get even an idea about what the code does and how. I'm pretty sure the more modern versions of VB at least allow a different more full view of the code but this together with the syntax that always seemed rather unstructured and ad hoc from a design view point made me avoid VB like the devil. C# is a bit better in that respect but after having dabbled in Java a bit I prefer it above C#. The only thing I don't like about Java is the fact that it doesn't support unsigned integers and other "low" level stuff. It makes interfacing to binary protocols for instance a bit more of a challenge since you have often to deal with proper sign extension and that sort of thing.
-
How to Implement Callback function using LabVIEW
Rolf Kalbermatter replied to Vivek Bhojan's topic in Calling External Code
You will need to learn some C AND LabVIEW for sure. The example in the link from vugie provides all that is necessary with only one difference and that is the prototype of your function itself. If your knowledge is so limited that this is to much to do yourself you will run into many more trouble along the way and should consider to either try to find a non callback solution or hire someone who does this part for you.