Jump to content

Using the DLL files of an application compiled with C# with labview


Recommended Posts

8 minutes ago, alvise said:

Then you say that choosing "UI thread" for "Play4M" and "HCNetSDK.dll" makes more sense for now.

 

No, the opposite if you have a DLL version 6.1.1.17 or newer. In that case it SHOULD be safe to set all Call Library Nodes for the PlayCtrl.dll functions to reentrant.

6 minutes ago, alvise said:

I have to use the method here, right?

No again! The byte stream coming from PlayM4_GetJPEG() is already a JPEG formatted byte stream. Dump into a binary file and it is a JPEG image. For Windows make sure to give it the filename extension .jpg or .jpeg as otherwise Windows Explorer will not understand that it is a JPEG image, but that is just a Windows thing. Microsoft in its infinite wisdom decided loooooooooong ago that the file ending is the only reliable way to determine what type a file is. Of course that is a very unreliable assumption but hey they have gotten away with it for about 40 years. So what!

Link to comment
4 minutes ago, alvise said:

saving to an image file and reading from the image file may cause some slowdown. What can be done as an alternative to this?

Yes, that is why it was an one-time test. Remove all that file writing stuff and add the Decode Image Stream VI instead. It will decode the stream in memory.

4 minutes ago, alvise said:

But I still don't understand how you solved this photo.

Obviously I just deleted first 4 bytes from the file as you forgot to connect the boolean constant and the VI was adding an extra integer of the array size to the beginning of the file. Plus it's known how the JPEG header starts, so it's relatively easy to find its first bytes in almost any file.

Edited by dadreamer
Link to comment
48 minutes ago, dadreamer said:

Obviously I just deleted first 4 bytes from the file as you forgot to connect the boolean constant and the VI was adding an extra integer of the array size to the beginning of the file. Plus it's known how the JPEG header starts, so it's relatively easy to find its first bytes in almost any file.

clever reasoning :)

48 minutes ago, dadreamer said:

Yes, that is why it was an one-time test. Remove all that file writing stuff and add the Decode Image Stream VI instead. It will decode the stream in memory.

 

I was able to read the video now and it was extremely delayed. And the labview started to get heavy again.
I think if I follow your previous suggestion (creating a parallel while loop), I will have solved this problem.(Does really adding all the playM4 calls to a parallel while loop fix the video slowdown and LabVIEW freezing?)

image.png.99ef740e9cb1584fddd9475efe8e3b00.png

Edited by alvise
Link to comment
1 hour ago, Rolf Kalbermatter said:

No, the opposite if you have a DLL version 6.1.1.17 or newer. In that case it SHOULD be safe to set all Call Library Nodes for the PlayCtrl.dll functions to reentrant.

I set it as you said. I think you said it's safe for us to choose this as the UI thread. But Only for PlayM4.

image.png.46c404e487c98f6b980ce697d5418cd5.png

Edited by alvise
Link to comment
3 hours ago, ShaunR said:

It solved the symptom, not the problem.

Yes, I think it just solved one symptom. In general, the problem persists. I guess it has an effect on the slow streaming received.

Edited by alvise
Link to comment

Currently I'm calling "PlayM4_GetJPEG" in a parallel while loop so that the data stream is faster and LabVIEW doesn't freeze, but for some reason "PlayM4_GetJPEG" is not returning any value, what could be the reason? The data seems to be passed to the second while loop without any problems looks.

What am I missing here?

Preview CAM-2.vi

Link to comment
1 hour ago, alvise said:

What am I missing here?

You should have moved only PlayM4_GetPictureSize and PlayM4_GetJPEG to a parallel loop. The other functions should remain as they are, i.e. in the callback event frame. Now as you moved everything PlayM4 related and did not introduce a minimum delay for the loop, your While loop runs with a very high frequency, not only hogging up the system resources, but also executing few unnecessary runs for one User Event! To clarify, in each callback event you need to call InputData once, but you call it one, two, three times in a row or even more!

Link to comment

Something like that, but...

- Why all your CLFNs are orange again?

- You did not introduce a minimum delay for the loop.

- Better to use some button, pressing which you would capture the image. So you would need a Case Structure or an Event Structure in that second loop to handle the button actions.

Link to comment
27 minutes ago, dadreamer said:

Something like that, but...

- Why all your CLFNs are orange again?

- You did not introduce a minimum delay for the loop.

- Better to use some button, pressing which you would capture the image. So you would need a Case Structure or an Event Structure in that second loop to handle the button actions.

-Are you saying they should all be yellow (Run in Any Thread).
I never understood this. From what Rolf said;
 ''HCNetSDK.dll'' and ''hikLabview-0.0.01.dll'' should have CFLNs  yellow(Run in Any Thread).
  ''PlayCtrl.dll''' CFLNs should be orange(Run UI thread). as I understood.

-I add -10 milliseconds wait

-Actually, I need to add a button to start the stream, but I want to start the stream automatically as soon as the VI is run. I don't want the user to press any button to start the video, I will try to render it.

Edited by alvise
Link to comment
13 hours ago, alvise said:

I set it as you said. I think you said it's safe for us to choose this as the UI thread. But Only for PlayM4.

image.png.46c404e487c98f6b980ce697d5418cd5.png

Sometimes I feel like I must be talking some obscure galactic slang or something!

Setting Call Library Nodes to run in UI thread is indeed safe but I never said this is required here.

Quote

If you use a PlayCtrl.dll version 6.1.1.17 or newer it SHOULD be safe to set the Call Library Nodes to run reentrant!

What about that English sentence is not clear? Have you looked at the last attachment I added to one of my last messages?

Link to comment
4 hours ago, Rolf Kalbermatter said:

Sometimes I feel like I must be talking some obscure galactic slang or something!

Setting Call Library Nodes to run in UI thread is indeed safe but I never said this is required here.

It's misunderstood, but not because you don't explain it well, but because I don't know some terms well and it's like someone learning to swim in a pool trying to swim in the ocean.

One point that confused me was this.
-Run in UI Thread: how it works and how it should be set.
-Run in Any Thread: how it works and how it should be set.
What is enterant and Reanterant and how is it related to UI thread or Any Thread.

Not understanding these in all its depth causes confusion. I am trying to understand it again by analyzing the Application we have created so far and taking into account the work it has done.

4 hours ago, Rolf Kalbermatter said:

What about that English sentence is not clear? Have you looked at the last attachment I added to one of my last messages?

I didn't see the edit you added. Because when I read your first post, that plugin was not there. I guess I was trying to understand what dadreamer was saying when you added it later.


The application you are editing is really neat and tidy.I tested the app you edited and it responded with an error like below.

erorr #define PLAYM4_INVALID_PORT 32 

image.png.737caa077b63e7a964fd96566d71b64a.png

image.png.68e0a8d3a7c1a4b7197e51edb4fdc890.png

Edited by alvise
Link to comment

The thread setting and execution mode (re-entrant vs non re-entrant) are set in the VI properties, under execution.

Re-entrant means that the OS (Or the LVRTE) can stop the VI's execution, switch to another thread, switch back, and the VI should continue as normal. Non-reentrant means the VI has to finish execution before such context switch happens, otherwise bad things (tm) happen.

Link to comment
3 hours ago, Gribo said:

The thread setting and execution mode (re-entrant vs non re-entrant) are set in the VI properties, under execution.

Re-entrant means that the OS (Or the LVRTE) can stop the VI's execution, switch to another thread, switch back, and the VI should continue as normal. Non-reentrant means the VI has to finish execution before such context switch happens, otherwise bad things (tm) happen.

Thanks for your answer, actually, what I wrote in the previous message is not that I don't know completely about this subject, I meant some things that I don't understand deeply.
For example; Why are we talking about reentrant and non-reentrant when using the Call library function node?

Warning: It's possible that everything I've said here is wrong!


Possible answer: Because we want to have parallel loops and the same subVI (for the previous Play4M_GetJpeg) may need to be run several times. Each time it is called in the subVI we are calling the same function (CFLN) again, and in this case the non-reentrant function if called at the same time can cause queueing. It means it wouldn't make sense to choose non-reentrant.
So why is the VI we use chosen as non-reentrant?
etc. many questions.


But at the current stage, some of the contradictions I mentioned above have disappeared, and there is no need for this at the last point that Rolf shared and in general we reached. because since the same set of gates are used by all callers of the VI, the values from the last call of that VI are available to the next caller.

By the way, sorry for my bad english.From everyone participating in the discussion on this forum.  :)

 

Edited by alvise
Link to comment
5 hours ago, alvise said:

Thanks for your answer, actually, what I wrote in the previous message is not that I don't know completely about this subject, I meant some things that I don't understand deeply.
For example; Why are we talking about reentrant and non-reentrant when using the Call library function node?

Warning: It's possible that everything I've said here is wrong!


Possible answer: Because we want to have parallel loops and the same subVI (for the previous Play4M_GetJpeg) may need to be run several times. Each time it is called in the subVI we are calling the same function (CFLN) again, and in this case the non-reentrant function if called at the same time can cause queueing. It means it wouldn't make sense to choose non-reentrant.
So why is the VI we use chosen as non-reentrant?
etc. many questions.


But at the current stage, some of the contradictions I mentioned above have disappeared, and there is no need for this at the last point that Rolf shared and in general we reached. because since the same set of gates are used by all callers of the VI, the values from the last call of that VI are available to the next caller.

By the way, sorry for my bad english.From everyone participating in the discussion on this forum.  :)

 

The Call Library Node itself is NEVER switching threads on the fly. When LabVIEW executes VIs it can arbitrarily switch between the multiple threads it has allocated for a particular execution system. But when it executes a Call Library Node it selects a thread (usually the one it was already executing the VI in except that thread is already tied up for something else) and passes control to the shared library function. LabVIEW has no way to take control back from this until the function returns control to the caller. The setting really is called "Execute in any thread", not "reentrant", but a function needs to be reentrant  or multi-threading safe in order for this to be safe.

If a function is not reentrant safe (for instance because it uses global resources such as a global variable or accessing some hardware, or is simply badly programmed) then you should not use the "Execute in any thread" setting since there could be situation where the shared library gets called multiple times in parallel when doing so and then the multithreading unsafe functions could stomp on each others global resources and cause race conditions or worse.

Then you can choose to run the nodes in the "UI thread" this is the only execution system in LabVIEW that is guaranteed to only use a single thread. So multiple Call  Library Nodes set to run in the "UI thread" can NEVER execute in parallel and therefore can not stomp on each others global resources or similar at the same time. But they also have to compete with many other things in LabVIEW that are required to execute in a single thread, including all screen updates. This can lead to very sluggish operation as each Call Library Node set to run in the UI thread has to wait for that thread to be available before it can call the shared library function.

If a shared library (or particular functions in a shared library) are multithreading safe is only something that can be answered by the original developer. However many developers have just like you no good idea what the issues could be and if asked about this they will simply give you an empty stare, wondering what you are talking about, respectively either saying that is isn't multithreading safe if they are the cautious type or boldly claiming that it of course is, if they prefer to look cool and are not ashamed to lie flat out.

In the case of the PlayCtrl.dll it states explicitly that since version 6.1.1.17 the DLL is multithreading safe. It mentions a caveat that it may block if you try to call certain shared library APIs from within a callback. This is because they seem to have made the library multithreading safe by using mutexes. An API that you call from your application acquires the mutex for that resource, preventing other threads to use that resource for the duration of the call. Before returning from that function the mutex is released. As long as your application only calls APIs it can't really deadlock. The worst that can happen is that some calls will have to wait for the mutex to be available again before they can start doing their work.

But if such an API causes callback functions to be called synchronously then it may hand off an already acquired resource to the callback which then calls a library API that tries to acquire its mutex too, but it can't get it until the original API has released the mutex, which it can't do until the callback returns. => Fatal deadlock.

 

Edited by Rolf Kalbermatter
Link to comment
18 hours ago, alvise said:

It's misunderstood, but not because you don't explain it well, but because I don't know some terms well and it's like someone learning to swim in a pool trying to swim in the ocean.

One point that confused me was this.
-Run in UI Thread: how it works and how it should be set.
-Run in Any Thread: how it works and how it should be set.
What is enterant and Reanterant and how is it related to UI thread or Any Thread.

Not understanding these in all its depth causes confusion. I am trying to understand it again by analyzing the Application we have created so far and taking into account the work it has done.

I didn't see the edit you added. Because when I read your first post, that plugin was not there. I guess I was trying to understand what dadreamer was saying when you added it later.


The application you are editing is really neat and tidy.I tested the app you edited and it responded with an error like below.

erorr #define PLAYM4_INVALID_PORT 32 

As said many times before. I can't test the software without hardware so this is all a dry swim exercise for me.Hikvision-labview SDK -Test-v1.1.1.zip

But try with this version, it should fix this particular problem. I excluded the lib folder as it is huge and has no changes in respect to the earlier version. So you need to extract this into your previous sources folder (but make sure to delete all LabVIEW VIs in there to avoid potential conflicts).

Link to comment

 

Thank you for your explanation.

After pressing the "Start" button, I get the following error without pressing the "Stream" button.
 

image.png.daeec0d45ddd91e637cd6587e33f81a6.png

The "User ID" here is increasing by a number with each new run, I guess, which means that it is logged in and not logged out again.

It doesn't return true at all here.

image.png.604aad41a0a012070d6a20acc6577a6f.png

 

Edited by alvise
Link to comment
1 hour ago, alvise said:

I think this application alone consumes 35-40% CPU. Is this normal? Or is there an error?

Not that normal for sure. Usually such a video translation takes about 10 to 15 percent of CPU load. I suggest to try:

- increase the loop delay from 10 to 50 ms;

- as you know, that your image size is constant (1280x720), eliminate the GetPictureSize CLFN completely and move the Initialize Array node outside the loop.

Link to comment

I think there is a problem now.
Although everything seemed to be working, the video was being received without any problems, but I read the video information without turning it off for a long time(1 hour). When I stop the application and try to run it again, the video information is no longer read. If I close the labview completely and open it again, I can get the video again.

I've tested this several times, it happens like this, what could be the reason?

 

 

 

Link to comment
1 hour ago, alvise said:

it happens like this, what could be the reason?

Very hard to tell. You need to check the functions return values one by one, and not only in LabVIEW, but in the DLL as well. Use DbgPrintf window to ease the debugging. To me it seems more like a call sequence mistake of some sort. But it may be resource leaking too, as if for example you'd forget to close some handle or free some pointer.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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