Jump to content

dadreamer

Members
  • Posts

    350
  • Joined

  • Last visited

  • Days Won

    34

Posts posted by dadreamer

  1. You don't need this!

    image.png.75279184373279dc508913e49aed9e35.png.4b1ea86e1cb9bea35600f1fda1740ed3.png

    This was just to demonstrate that when the Image object is initialized, no errors occur on reading after.

    22 minutes ago, alvise said:

    but I did not add the event structure to read the picture because the event structure only works once when the start button is pressed.

    My bad, I didn't realize that when answering πŸ˜ƒ Then you should move that PictureBox reading into a parallel While loop and see, what will happen. This way you're not synchronizing the threads and may miss some data frames though (due to different rates of the loops).

  2. You happen to read the Image object, when it's not instantiated yet, hence you receive 1172 error. You need to read it out only after your image data is loaded into the PictureBox control.

    2022-05-26_10-11-27.jpg.e2a59bbb1e5e2a4131af446ec26352d3.jpg

    Try to add your code piece into the Value Change frame plus add a simple NULL check. That should work, but if not, then you need to find a way to synchronize image write thread with image read thread (with callback that would be easier).

  3. 6 minutes ago, Rolf Kalbermatter said:

    Now the entire softlib subdirectory and all its contents is not browsable anymore.

    Was it ever browsable? As I recall I've never been able to browse softlib directory. Maybe because I often don't login to NI site or don't have a valid SSP, when trying to fetch the server content.

    They might introduce a hash system for the files as applied on many file sharing services (to force visitors to watch the ads). Then nobody would be able to browse through their servers. But it'll break many links, which are settled down in the manuals and other papers.

  4. 1 hour ago, Rolf Kalbermatter said:

    Already terminated, ahem, I mean expired. ☠️

    There's something with your browser/connection/cookies/firewall/etc., because I downloaded both archives right now and nothing interrupted me. Anyway even if the links go dead, you know who to ask about reupping. πŸ˜‰

  5. If you want to manipulate array pointers directly on the diagram, why not use convenient Memory Manager functions such as DSNewPtr / DSNewPClr? You may call them through the same CLF Nodes as you already do with MoveBlock function. Just allocate enough memory with DSNewPtr, copy the array contents to there with MoveBlock and then do what you want. Or, if you prefer hacky ways, you could use internal ArrayMemInfo node and process arrays "in-place", without getting extra copies on data transfers. In the latter case it's necessary to realize that the pointer will be 'alive' as long as you pull the array wire through the structures. At the moment you decide to drop that wire somewhere, LabVIEW wants to optimize your code and the pointer becomes invalid or occupied by something else in the next structures.

    But, as it has been said above, LV native yellow nodes should already be optimized and should satisfy your needs in most cases. If not, then process your array in DLL entirely and give that array back to LV, when it's done completely. As long as you are in the DLL doing something with the data, the array pointer should be fine.

    upd: You changed your snippets and seem to use Memory Manager allocation functions now. Still I don't get the grand design of these experiments. Maybe I should wait a little. πŸ˜€

  6. 8 hours ago, Rolf Kalbermatter said:

    Edit: I'll be damned! A VI inserted into a Subpanel does not have a window handle at all. I thought I had tested that but somehow got apparently misled in some ways. LabVIEW seems to handle that all internally without using any Windows support for that. So back to the drawing board to make that not a Subpanel window but instead using real Windows Child window functionality. I don't like to use the main VIs front panel as the drawing canvas as the library would draw all over the front panel and fighting LabVIEWs control and indicator redraws.

    I managed to check that on few machines with few LabVIEW versions, including 2011, 2013, 2018 and 2019 (32- and 64-bit) as I seldomly use subpanels and never ever wondered about how the VIs are embedded. Looks like this is the case, when an old-fashioned MDI relation has an advantage of providing handles to operate the windows on OS level. Sure, you know, that it could be done with SetParent function. But there are a lot of disadvantages and odd issues too, so it's a doubtful method. As I remember, there's private Open In Native Window method, that tries to supersede an obsolete Open In Window method. The latter works well in LV8.5, but doesn't work absolutely in LV 2009 and higher. But the new method doesn't work anywhere at all! I have spent more than a week trying to understand why. Still sort of a mystery, but I think there was a mistake made in the code, when introducing the new method. There's something wrong with the window styles and that's why the child window doesn't get embedded into the parent window. Interesting puzzle but almost an off-topic here. πŸ™‚

  7. Maybe there's something I'm missing. I tried to debug Rolf's example a bit. It appears that I'm getting zero HWND for the subpanel VI as well! Could it be that NI changed the way VI's are inserted into the main VI? WinSpy++ doesn't even show the window of "Empty.vi" anywhere in the windows hierarchy. I'm using LabVIEW 2019 32-bit right now. Seems to need more testing on different LV versions.

    Moreover Get Last Error.vi was reporting an error in NET_DVR_GetErrorMsg configuration. This function has the following prototype:

    char* NET_DVR_GetErrorMsg(
      LONG   *pErrorNo
    );

    But in the CLFN settings pErrorNo was passed as value, not as pointer to value. After the fix it started to work as intended.

  8. 16 minutes ago, Rolf Kalbermatter said:

    And before you cry victory, consider another very important point: The SDK library will push data down your callback no matter if you process them in LabVIEW or not. If your user event loop serving that user event is not ready or can't keep up with that data stream, the user event queue in LabVIEW will get stuffed with event data messages with potentially huge byte array data in them and after some time it will simply post a threaded Out Of memory dialog that gives you exactly one option, to abort everything and lose whatever work you have not yet stored. So beware!!!!

    There is a nasty effect, when this is happening. You may notice, that the image on your panel indicator starts to lag behind what is going on before the camera. Easy to verify with moving the camera or the objects in front of it. Event Inspector window is of help here as well, showing that the events are being accumulated and not being processed in time. When no need to view or process each and every frame of the data, I usually introduce a boolean flag, that could allow or deny posting from the DLL to LabVIEW. Most of the time the flag is False and the callback is idling. When I need the data to process, I set the flag to True, grab some frames and set it to False right after. Usually there's no more than a few cameras in the system and this works well.

  9. 14 hours ago, alvise said:

    Do I understand correctly what you are saying? I still need to create a .dll in C++ to use the labview code you shared here.

    I can't speak for anyone else, but from what I saw, Rolf's example should work "as is", without any callbacks or something extra. I can't say, why it doesn't work on your side. But it should.

    14 hours ago, alvise said:

    I need to compile the code below (after adapting the part added as C# code to C/C++ language) and create the .dll file, right?

    Well, you have two options here. You may try to figure out, why Rolf's example doesn't want to work, and fix it on your own. Or you could write the callback DLL and integrate it into your previous samples (from page one of this thread). Of course, if you can fix Rolf's example and write the callback, then you may combine two options into one and get best example for that camera.

    14 hours ago, alvise said:

    If this step is correct I think I need to make some plugin in the labview code you shared that should get this callback.Live video output can be seen after adding the callback plugin as well.

    Don't insert any C# code, just try to compile it into a library and report the progress. You should receive a standard DLL, that's exporting two functions: SendEvent and g_DataCallBack. Check that they both are present.

  10. 14 hours ago, alvise said:

    - I need to write a piece of code in C++ and in this code I need to communicate with the labview by importing the extcode.h header file and using the PostLVUserEvent function. I will do this just to understand the communication between the dll I created and the labview.
    Doesn't this example here already do that?

    You are right. By the way that is the example, that I used a while ago to study PostLVUserEvent just like you do. But you don't need the string manipulations from there. You're going to pass pBuffer pointer to LabVIEW with PostLVUserEvent function inside your callback and you should be done.

    14 hours ago, alvise said:

    -In C++ code, I will import the header file HCNETSDK.h and extcode.h, then call the PostLVUserEvent function and adapt the callback from labview with this function to the following snippet and finally I will compile this code and create a dll file.

    Looking at your C code I see, you're doing more or less good. But you don't even need to implement the main function, because all the work with the cameras is made in your LabVIEW application entirely. You could remove that code at all. Besides the callback function you'll need one extra helper function, that would set your User Event refnum to some global variable in your DLL. That's needed, because when you'll want to call PostLVUserEvent, you'll need that refnum and you could take it out of that global variable.

    Something like this:

    #include <stdio.h>
    #include <iostream>
    #include <time.h>
    #include "Windows.h"
    #include "extcode.h"
    
    using namespace std;
    
    LVUserEventRef *pUE;
    
    void SendEvent(LVUserEventRef *rwer)
    {
      pUE = rwer;
    }
    
    void CALLBACK g_DataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
    {
      //your callback code here
      // ...
      //PostLVUserEvent(*pUE, (void *)&pBuffer); is here as well
    }

    Likely will require some small fine-tuning like adding extern "C" { ... } to escape functions name mangling.

    • Thanks 1
  11. 1 hour ago, alvise said:

    I also want to pass, but I don't know exactly how. To use the PostLVUserEvent function, the extcode.h header file must be added to the C# code, but that is a separate event for how to do it in C#.

    Now, after you've succeeded with C# examples, I'd advice to put them aside and try to build a very basic C/C++ DLL in your editor. Maybe start with something trivial like a sum of two numbers or even empty function, returning a constant. After you get your DLL, try to call it in LabVIEW. On success, you may go further, introducing "extcode.h", PostLVUserEvent and slowly turning your function into the callback.

    Also I'd like to ask about your LV code. Why do you use Event structure without While loop? That sample should also do the job. And maybe a good idea to take NET_DVR_Logout_V30 and NET_DVR_Cleanup out of the loop, so they'd get executed anyway.

  12. 3 hours ago, Rolf Kalbermatter said:

    They and others have repeatedly provided installer downloads that are supposedly cracked to circumvent the serial number license check. If that is true or if they are actually modified with other less friendly hacks that may install a backdoor on your system instead, or maybe a nice cryptolocker ransomware, is always the big question. 😝

    I've never ever encountered such releases, if speak about LabVIEW and other NI software. Maybe they were pre-LV2009 releases with some 'evil' cracks, but from what I saw, people are seeding mostly genuine files plus some tiny ... eh... "cure", that does nothing except modifying those *.lic's in \ProgramData\National Instruments\License Manager\Licenses. But I don't encourage anyone to use torrents. Why bother, when it's often enough to google a little to find the links to the distros πŸ™‚ (if not already collected).

  13. You need to create a standard native Windows library (DLL). You may use any IDE of your choice, that's able to do that, e.g. Microsoft Visual Studio (Community Edition is fine as well). In that IDE you need to export the function with the following prototype:

    typedef void(CALLBACK *REALDATACALLBACK)(
      LONG      lRealHandle,
      DWORD     dwDataType,
      BYTE      *pBuffer,
      DWORD     dwBufSize,
      void      *pUser
    );

    Make sure your exported function matches it exactly. Also you need to include "extcode.h" from [LabVIEW]\cintools directory, because you're going to use PostLVUserEvent LabVIEW Manager function. The logic is that you don't do anything in your callback except calling PostLVUserEvent, passing pBuffer into it. But if you want to use more than one camera in parallel, then more logic is needed. You could try to use lRealHandle or pUser parameters to distinguish the cameras. Start with an easy setup of one camera for now. In LabVIEW you need to call LoadLibrary and GetProcAddress functions from Windows API, in order to load you DLL and get the address of your callback. You pass this address into NET_DVR_RealPlay_V40 upon the call. After that you register your user event and wait for it in your Event Structure. If everything is done right, you should receive the events right after calling NET_DVR_RealPlay_V40. Read vugie's post in the topic, I linked above, to get the main idea.

    Also please don't mix C# and C/C++ here, they are different beasts. Of course, you may learn from C# examples, but you're trying to use C/C++ written library through CLFN's, so you need to use C/C++ language to create the callback. If you were to use C# and .NET assemblies, you'd use instruments from the .NET palette.

  14. Well, it's time when things get more complicated. The NET_DVR_RealPlay_V30 function needs a callback function to be registered, in order to transfer live stream data. But it's not that easy to implement callbacks in LabVIEW. You would have to write a small wrapper DLL, that would receive the data and pass it to LabVIEW with PostLVUserEvent function and then in LabVIEW you'd be able to catch those events in your Event Structure. Are you sure, you can't work with these cameras using NI-IMAQ(dx) and NI Vision? Can you see your camera in NI-MAX? As an alternative, you could try to use VLC API, if the camera transfers common RTSP stream and you know its address.

  15. Still not everything is correct on your diagram. Since lpDeviceInfo is an output parameter of that NET_DVR_Login_V30 function, it requires the memory to be allocated before the function is called. You can't feed an uninitialized pointer into the function. In LabVEW to pass a struct into a function you have to make a properly sized cluster (of 80 bytes in our case) and wire it to the CLF Node. This is how NET_DVR_DEVICEINFO_V30 struct is declared:

    struct{
      BYTE     sSerialNumber[SERIALNO_LEN];
      BYTE     byAlarmInPortNum;
      BYTE     byAlarmOutPortNum;
      BYTE     byDiskNum;
      BYTE     byDVRType;
      BYTE     byChanNum;
      BYTE     byStartChan;
      BYTE     byAudioChanNum;
      BYTE     byIPChanNum;
      BYTE     byZeroChanNum;
      BYTE     byMainProto;
      BYTE     bySubProto;
      BYTE     bySupport;
      BYTE     bySupport1;
      BYTE     bySupport2;
      WORD     wDevType;
      BYTE     bySupport3;
      BYTE     byMultiStreamProto;
      BYTE     byStartDChan;
      BYTE     byStartDTalkChan;
      BYTE     byHighDChanNum;
      BYTE     bySupport4;
      BYTE     byLanguageType;
      BYTE     byVoiceInChanNum;
      BYTE     byStartVoiceInChanNo;
      BYTE     byRes3[2];
      BYTE     byMirrorChanNum;
      WORD     wStartMirrorChanNo;
      BYTE     byRes2[2];
    }NET_DVR_DEVICEINFO_V30,*LPNET_DVR_DEVICEINFO_V30;

    This NET_DVR_DEVICEINFO_V30 struct is a bit bulky to form, so here's a VI from which you can copy it and paste to your own VIs.

    NET_DVR_DEVICEINFO_V30.vi

    Now in your CLFN set this 5th parameter as Adapt to Type -> Handles by Value. With such a setting LabVIEW will pass a pointer to the NET_DVR_DEVICEINFO_V30 cluster and after the function call you should receive it filled with some device data.

    Also to note, LONG is I32 on Windows, not I64.

×
×
  • Create New...

Important Information

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